Skip to content

Capabilities

What z0 SDK does: Event-sourced ledger system for building immutable, traceable systems on Cloudflare Workers.

What: Immutable event records (Facts) are the source of truth. All state is derived from Facts.

When to use:

  • Need complete audit trail of all changes
  • Building financial systems requiring immutability
  • Implementing GDPR-compliant data tracking
  • Supporting point-in-time reconstruction

When NOT to use:

  • Simple CRUD apps where audit history isn’t needed
  • Real-time gaming (latency-sensitive, not business-critical)
  • Static file hosting

What: Entities are identity containers. One Durable Object per Entity for perfect isolation.

When to use:

  • Multi-tenant SaaS (tenant isolation built-in)
  • Systems requiring per-entity transaction guarantees
  • Applications with complex entity relationships

When NOT to use:

  • Need cross-entity queries (use D1 replication for analytics)
  • Entities have no unique identity (use KV or R2)

What: Configuration changes create new versions instead of overwriting. Time-based activation with effective_at.

When to use:

  • Pricing rules that change over time
  • Feature flags with scheduled rollout
  • Routing policies with audit trail

When NOT to use:

  • Static environment variables
  • Per-request context (use middleware)

What: WebSocket and SSE support for streaming entity changes to clients.

When to use:

  • Real-time dashboards
  • Live notifications
  • Collaborative editing

When NOT to use:

  • Static reports (use snapshot endpoints)
  • One-time queries

What: Denormalized views (CachedState) derived from Facts. Can be rebuilt anytime.

When to use:

  • Expensive aggregations (balance, usage totals)
  • Frequently-read derived data
  • Performance-critical queries

When NOT to use:

  • Storing source data (use Facts)
  • Cross-entity aggregations (use D1)

What: Parent-child entity relationships with depth limits and cached parent data.

When to use:

  • Organization → Team → User hierarchies
  • Account → Sub-account structures
  • Nested resource ownership

When NOT to use:

  • Graph relationships (many-to-many)
  • Flat data structures

What: TypeScript-first schema builders OR YAML manifests for entity definitions.

When to use:

  • Type-safe domain modeling
  • Validation at fact append time
  • Generating docs/tests from schemas

When NOT to use:

  • Schemaless/freeform data (use raw JSON)

What: Declarative HTTP routing with type-safe contracts, authentication, and rate limiting.

When to use:

  • Building REST APIs on Cloudflare Workers
  • Contract-first development with OpenAPI generation
  • Need built-in auth, rate limiting, validation
  • Want consistent API response formats

When NOT to use:

  • GraphQL APIs (no GraphQL support)
  • WebSocket-only APIs (use real-time subscriptions directly)
  • Static file serving

Key features:

  • Routes in YAML - Define HTTP routes alongside entities
  • GatewayWorker base class - Extend for automatic routing and middleware
  • oRPC contracts - Type-safe action interfaces with Zod validation
  • Auth middleware - API key authentication built-in
  • Rate limiting - Per-route rate limits (tenant/global scope)
  • Response shaping - Standard envelopes ({ data, meta }) and RFC 7807 errors
  • Code generation - Generate complete Workers from manifests
  • OpenAPI generation - Auto-generate OpenAPI 3.0 specs from contracts

Actions available:

  • emit - Append a fact to an entity
  • get - Retrieve an entity by ID
  • create - Create a new entity
  • list - List entities with cursor pagination
  • query - Execute projection queries

Included:

  • ID generation with prefixes
  • RFC 7807 error handling
  • Webhook signing and delivery
  • Tiered pricing calculation
  • Threshold monitoring
  • Batch operations with resumability
  • Circuit breakers for DO-to-DO calls
  • Rate limiting with backpressure
  • Temporal resource binding (phone numbers, email addresses)

What: Mock Durable Object context, stubs, and queues for unit testing.

When to use:

  • Testing EntityLedger subclasses
  • Mocking DO dependencies
  • Isolated ledger tests

ProjectionEngine: Fact aggregations from YAML config (sum, avg, count, max, min) MeterEngine: Usage tracking and budget enforcement

  • One Entity = One Durable Object
  • Perfect tenant isolation
  • No cross-entity queries (by design)
  • Facts auto-replicate to D1 (analytics)
  • Facts optionally replicate to R2 (archival)
  • DOs remain the source of truth
  • States: active → retiring → retired → anonymized → deleted
  • GDPR compliance with anonymization
  • Dead-lettering rejected facts
  • Schema versioning for facts
  • Data tier transitions (hot → warm → cold)
  • Backward-compatible migrations
LimitValueWhy
Max hierarchy depth10Prevent infinite recursion
Default query limit1000 factsMemory/performance
WebSocket subscribersPer DO limitMemory in DO
Config versionsUnlimitedStored in SQLite
Fact immutabilityForeverAppend corrections, never mutate

Cloudflare Infrastructure Limits (CRITICAL)

Section titled “Cloudflare Infrastructure Limits (CRITICAL)”

These are platform constraints that affect architectural decisions:

ServiceLimitImpact
Analytics Engine90 days retentionHistorical data beyond 90 days is lost. For long-term analytics, replicate to R2/external storage.
D1 Database10GB per databaseLarge datasets need sharding or external DB
D1 Rows100M rows per databasePlan for horizontal scaling
Durable Object Storage10GB per DOPartition large entities
DO Request Duration30s (default), 15min (paid)Long-running operations need queues
DO Memory128MBWatch CachedState size, paginate large queries
KV Value Size25MBSplit large objects
R2 Object Size5TBEffectively unlimited for archival
Queue Message Size128KBSerialize large payloads to R2
Queue Batch Size100 messagesPlan batch processing
Worker CPU Time10-50ms (free), 30s (paid)Offload heavy computation
Worker Memory128MBStream large responses
Subrequest Limit50 (free), 1000 (paid)Batch DO calls
ConstraintDurationMitigation
Analytics Engine data90 daysExport to R2 before expiration
DO hibernationAfter 10s idleUse alarms for scheduled work
WebSocket idle timeout60sSend heartbeats
Queue retry window4 daysDead-letter unprocessable messages

Analytics Engine 90-day limit:

// ❌ DON'T: Rely on Analytics Engine for historical reports
const yearlyReport = await analytics.query('SELECT ... WHERE timestamp > DATE_SUB(NOW(), 365)');
// Data older than 90 days is GONE
// ✅ DO: Archive to R2 for long-term analytics
await env.ARCHIVE_BUCKET.put(
`analytics/${year}/${month}/data.json`,
JSON.stringify(monthlySnapshot)
);

D1 row limits:

// ❌ DON'T: Assume unlimited D1 growth
// With 100M row limit, high-volume fact replication can hit limits
// ✅ DO: Implement retention policies
await env.DB.exec(`
DELETE FROM facts
WHERE timestamp < datetime('now', '-6 months')
AND archived_to_r2 = true
`);

DO memory constraints:

// ❌ DON'T: Load all facts into memory
const allFacts = this.getFacts(); // Could OOM with large history
// ✅ DO: Paginate and stream
for await (const batch of this.getFactsPaginated({ limit: 100 })) {
// Process batch
}

Published: npm @z0-app/sdk License: MIT Platform: Cloudflare Workers + Durable Objects Language: TypeScript

  • UI framework (bring your own)
  • Authentication provider (use Clerk, Auth0, etc.)
  • Database ORM (uses raw SQLite)
  • HTTP framework (compatible with Hono, Itty Router, etc.)
  • Cross-entity joins (use D1 replication)