The fabric
Select any node — each one says what it owns and how it dies.
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.
Why a Durable Object
Section titled “Why a Durable Object”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;
psreads 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: the Worker Loader fabric
Section titled “Facets: the Worker Loader fabric”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).
Design constraints
Section titled “Design constraints”| 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.