Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/denoland/celld/llms.txt

Use this file to discover all available pages before exploring further.

celld is currently in alpha. The core runtime is functional and tested, but several operational and platform boundaries exist that you must understand before building on it. This page documents the known constraints of the current release.
Every configuration key, binding type, or API that celld does not support is designed to fail loudly — at deploy time or at first use. A silent compatibility gap is a bug; report it if you encounter one.

One application per fleet

A celld fleet runs exactly one application deployment. There is no multi-tenant scheduler, no account service, and no managed ingress. To run multiple applications, run multiple fleets, each with its own bucket and credentials.

No local filesystem mode

celld requires an S3-compatible or Google Cloud Storage bucket even for local development. There is no local filesystem mode.
Local development needs either a real cloud bucket or a local object-store that implements conditional writes correctly (see Ownership and Fencing for the exact requirements). MinIO community edition does not qualify. Options that work locally include a real S3 or R2 bucket, or a local store with a compliant conditional-write implementation.

No TLS termination

The peer HTTP protocol does not terminate TLS. Do not run fleet nodes on a public network without an encrypted overlay or a private network.
  • Run the internal listener on a private network or an encrypted overlay such as WireGuard or Tailscale.
  • Terminate public TLS in an ingress proxy (nginx, Caddy, a cloud load balancer) in front of the --listen port.
celld does not provide TLS certificates or termination for either listener.

Bucket as administrative authority

The fleet bucket is the root of authority for the fleet. Bucket credentials give full control over all deployments, all cell state, all ownership records, and the peer-authentication secret.
  • Give each credential access to one fleet bucket only.
  • celld does not make shared object-store credentials safe — narrow the scope before use.
  • celld does not read ~/.aws profiles or SSO logins. Credentials come from AWS_* environment variables, instance metadata, or web identity tokens.
  • A gs:// bucket authenticates with Google Application Default Credentials or a service account key from GOOGLE_APPLICATION_CREDENTIALS / GOOGLE_SERVICE_ACCOUNT_KEY. S3 static credentials do not apply to GCS buckets.

Platform support

PlatformStatus
Linux x86-64✅ Prebuilt binary
Linux ARM64✅ Prebuilt binary
macOS ARM64✅ Prebuilt binary
macOS Intel (x86-64)⚠️ No prebuilt binary; build from source
Windows❌ Not available

WebSocket routing

Each node can serve as the WebSocket ingress for any cell through a signed peer tunnel. However, test coverage for WebSocket close codes and reconnection behaviour across nodes is thinner than for the single-node case. If latency is important, route WebSocket traffic for a cell directly to the node that owns that cell rather than relying on the peer tunnel.

Outbound Durable Object WebSockets

An outbound Durable Object WebSocket keeps its cell resident. If the cell moves to a different node — due to eviction, shutdown, or pressure shedding — the outbound WebSocket connection does not continue on the new node. To handle this correctly:
  • Store the connection intent in the cell’s SQLite database.
  • Reconnect after the cell is activated on the new node.
A Worker’s outbound socket stops with its request, the same as on Cloudflare. A node also limits how much residency the outbound sockets collectively can hold.

No automatic rebalancing

celld has no central placement controller. When a new node joins the fleet, it does not pull cells from existing nodes. Cells move to the new node only when:
  • A cell is released by its current owner (on shutdown or under pressure).
  • A new request arrives for an unowned cell, and the new node wins the ownership race.
Normal traffic gradually distributes cells across nodes as they activate and hibernate. There is no explicit rebalance command.

Manual updates

The installer keeps immutable release binaries behind a single current pointer. A rollback is achieved by re-running the installer with the previous release tag. There is no automatic update agent. Updates are always operator-initiated. For a fleet-wide update, use a rolling restart — stop each node with SIGTERM, wait for its replacement to report healthy at /__celld/health, and move to the next node.
The upgrade from v0.1.0 to v0.2.0 must not be a rolling update. Stop every v0.1.0 node first, then start the v0.2.0 nodes. The two versions use incompatible advertised-address formats and incompatible replication block formats; a mixed fleet will not function correctly.

Worker surface limitations

The following Cloudflare Workers APIs are not available in the current release:
APIStatus
HTMLRewriterNot available
Cache API (caches)Not available
KV namespacesNot available (out of scope; different consistency model)
R2 bucketsNot available (out of scope; r2_buckets bindings load but every method throws)
Cron triggers (scheduled handler)Not available
Custom domainsNot available (platform surface)
EventSourceInert stub — class exists so bundles load, but does nothing
MessageChannelInert stub
BroadcastChannelInert stub
TCP sockets (cloudflare:sockets)Known silent gap — connect() returns an inert stub rather than throwing
For the complete surface of what celld does run — including all available runtime APIs, RPC, static assets, WebSockets, and node compatibility — see the Cloudflare Compatibility page.
All gaps that should fail loudly do fail loudly, either at deploy time or at first use. If an unsupported API or configuration key fails silently in your application, that is a bug — please report it.

Build docs developers (and LLMs) love