Skip to content

The fabric

clientbrowser / SDKterminal · editorhttps · websocketone sessionsupervisor — the session DOsqlite disk · shell · process tableport registry · session agentone-shotnode · py · wasmspawn → exitresidentvite · flask · servekeyed · has portsgit enginefetch · indexchunked checkoutloopback 127.0.0.1:<port> — routed by the supervisorevery facet: its own isolate, its own 128 MiB, evictableplatformpeer DOsnpm install shardsR2 + edge cachetarballs · runtimes · bundleshot reads cached per-colo

Select any node — each one says what it owns and how it dies.

The supervisor holds the state that must survive a crash. Everything else runs in facets and can be evicted.

Every process runs in its own isolate. The 128 MiB per-isolate limit and per-invocation CPU budgets are Cloudflare’s published figures. Durable Objects are the only durable, strongly consistent primitive on the platform, so the supervisor owns the disk, shell, process table, and port registry. Facets do the work and can be evicted.

An app can span several isolates. That’s how opencode runs as a server and TUI joined by loopback, with a separate budget for each half.

Workers are stateless and can run anywhere; a sandbox needs one place where the working directory, the process table, and the disk agree. A Durable Object is the only Cloudflare primitive that is both durable and strongly consistent: a single-threaded actor with transactional SQLite storage attached. One session is exactly one DO instance, addressed by tenant:sessionId. There is one instance per session and no replicas, so there is no cache-coherence protocol to run.

The supervisor holds, in one actor:

  • The disk — the SQLite-backed VFS, 10 GB, the single source of truth for every byte (inside the disk).
  • The process table — pid-keyed state that survives facet resets; ps reads the DO, never a facet. Each process carries an immutable credential (uid, gid, groups, umask) assigned at spawn.
  • The port registry — which pid owns which port, and the facet stub that serves it (ports & routing).
  • Per-process log ring buffers and input queues — durable and bounded, so logs <pid> works after a facet dies.
  • Hibernatable WebSockets — terminals survive DO eviction, and configured auto-responses answer idle pings without waking the actor.

The supervisor enforces a soft heap ceiling on itself of 64 MiB, half the platform cap. A supervisor OOM resets the whole session rather than failing a single process, so heavy work is pushed out to facets.

Facets are dynamically loaded Workers created through the platform’s Worker Loader binding. Each gets the standard nodejs_compat runtime, a 128 MiB heap of its own, and exactly one injected capability: a SUPERVISOR RPC stub pointing back at its own session. Generated facet code cannot import supervisor modules — the RPC surface is the whole contract.

The loader keys isolates by content hash and slot, so repeated runs of the same program reuse a warm isolate instead of re-instantiating. Warm reuse also sets the failure rule: a route stub for an evicted facet fails loudly rather than re-loading the code, because a re-loaded isolate is an empty worker with nothing listening.

The supervisor describes a big app with a small spec — argv, env, a bounded VFS snapshot — and the full module map is assembled outside the DO, in a stateless isolate on the loader’s cache-miss path. opencode’s map is roughly 20 MB. Assembling it inside the supervisor crossed the memory cap and reset the session in testing, so assembly runs outside the DO.

Writes flow one way. Facets never own files. Every mutation streams to the supervisor through a credit pool, so a parallel npm install can’t flood the DO (inside the disk has the numbers).

Constraint Cloudflare’s figure What it produced
Isolate memory 128 MiB each multi-isolate processes; staged module maps
DO SQLite storage 10 GB per object the session disk
CPU per invocation 30 s default, 5 min via limits.cpu_ms phased git clone, sliced checkout, fan-out installs

A raised cpu_ms applies to the supervisor. Facets keep ~30 s, so long facet work must be split into phases. When the DO hibernates, its disk stays.

Nimbus inherits workerd’s isolation, the same primitives Cloudflare runs untrusted customer code on. The CSP allows no runtime eval and no request-time WASM compilation. Sessions share only read-only, content-addressed caches, and loopback stays inside a session. Security covers the full model — isolation, Unix permissions, tokens — and its current gaps.