How celld Achieves Cloudflare Workers and Durable Objects API Compatibility

celld reproduces the Cloudflare Workers runtime and Durable Objects API by embedding V8 to execute Wrangler-bundled modules, implementing Durable Objects as isolated SQLite-backed cells with S3 replication, and exposing the full Workers surface including RPC, alarms, and WebSockets through a JavaScript harness.

The denoland/celld project provides a self-hosted runtime that achieves complete Cloudflare Workers and Durable Objects API compatibility without relying on Cloudflare's infrastructure. By combining a V8-based JavaScript engine with a bespoke storage layer and distributed ownership protocol, celld enables developers to deploy existing Workers applications to any infrastructure while maintaining the exact semantics of Durable Objects state management and coordination.

V8-Based Workers Runtime Engine

Each celld node embeds V8 to execute JavaScript modules bundled by Wrangler, exposing the complete Workers runtime surface. In crates/celld/runtime.rs, the runtime bridges the V8 isolate with Rust to handle module loading, providing standard APIs including fetch, environment variables, and service bindings. This implementation matches the compatibility specifications documented in docs/cloudflare-compat.md, ensuring that standard Web Platform APIs and Workers-specific features behave identically to Cloudflare's production environment.

The runtime executes Wrangler-bundled modules directly, requiring only esbuild available on PATH during the build phase. This approach allows existing Workers projects to migrate without code changes, as celld handles the exact same module formats and global scope expectations.

Durable Object Cell Architecture

At the core of celld's Durable Objects implementation is the cell abstraction. Every Durable Object class is instantiated as a cell with isolated state management, replicating the semantics of Cloudflare's single-owner, single-threaded execution model.

SQLite-Backed State Management

Cell state persists in isolated SQLite databases managed by crates/celld/storage.rs. The DurableObjectStorage implementation in crates/celld/js/harness.js provides the exact storage API expected by Cloudflare, including transactional get, put, delete, and list operations. This JavaScript harness wraps the Rust storage layer, exposing the familiar this.state.storage interface to Durable Object classes.

export class Counter extends DurableObject {
  async fetch(request) {
    const value = await this.state.storage.get('val') ?? 0;
    await this.state.storage.put('val', value + 1);
    return new Response(`${value + 1}`);
  }
}

The DurableObject base class referenced above is provided by harness.js, ensuring that class inheritance and lifecycle methods match Cloudflare's implementation exactly.

Replication and Ownership Protocol

Cells replicate to an S3-compatible bucket using the protocol defined in crates/celld/protocol.rs. Rather than implementing a distributed consensus algorithm, celld uses object-storage compare-and-swap operations to establish ownership. This guarantees that at most one node owns a cell at any moment, providing the same single-threaded execution guarantees as Cloudflare's Durable Objects without requiring additional coordination services.

When a node needs to process a request for a specific Durable Object, it attempts to acquire ownership through the bucket protocol. If successful, it loads the cell's SQLite database from S3 and processes the request; otherwise, it redirects or queues the request appropriately.

Complete API Surface Implementation

Beyond basic storage and compute, celld implements the extended Durable Objects API surface including coordination primitives and real-time communication.

Alarms and WebSocket Support

The runtime implements Durable Object alarms through the alarm handler, allowing scheduled execution exactly as Cloudflare does. For real-time communication, celld supports inbound hibernatable WebSockets and outbound ws:/wss: clients, maintaining the same connection semantics and state restoration patterns documented in docs/cloudflare-compat.md.

JavaScript RPC System

celld ships with the same JS RPC system used by Cloudflare Workers, including WorkerEntrypoint, RpcTarget, and Durable Object stubs. The implementation serializes calls using structured-clone semantics and pipelines them across isolates. This enables method invocation on Durable Objects using standard JavaScript class patterns rather than HTTP requests, matching the behavior described in the compatibility documentation.

export default {
  async fetch(request, env) {
    const counterId = env.COUNTER.idFromName('global');
    const counter = env.COUNTER.get(counterId);
    const resp = await counter.fetch(new Request('https://example/'));
    return new Response(`Counter: ${await resp.text()}`);
  },
};

The env.COUNTER binding is automatically populated by celld when the Worker declares the class in wrangler.json, exposing the same stub interface used in Cloudflare's environment.

CLI and Deployment Workflow

The celld deploy command builds Wrangler projects and writes the compiled bundle directly into the configured S3 bucket. Nodes automatically pull the latest deploy/current.json on startup, enabling seamless rolling deployments across a cluster.


# Build and upload the bundle

celld deploy . --bucket s3://my-cells-bucket

# Start a node that will run the Worker

celld \
  --bucket s3://my-cells-bucket \
  --listen 0.0.0.0:8080 \
  --advertise node-a.internal:8080

This deployment model eliminates the need for a centralized control plane. The bundle written to deploy/current.json contains the complete Worker code, which each node loads into its V8 isolate upon initialization.

Summary

  • celld embeds V8 to execute Wrangler-bundled Workers modules with full API compatibility.
  • Durable Objects are implemented as cells with SQLite-backed storage in crates/celld/js/harness.js and crates/celld/storage.rs.
  • S3-compatible object storage handles replication and ownership via compare-and-swap operations defined in crates/celld/protocol.rs.
  • Extended APIs including alarms, WebSockets, and JS RPC match Cloudflare's implementation details.
  • Self-hosted deployment uses celld deploy to write bundles directly to object storage, with nodes pulling configuration automatically.

Frequently Asked Questions

Is celld a drop-in replacement for Cloudflare Workers?

Yes. According to the denoland/celld source code, the runtime implements the full Workers and Durable Objects API surface documented in docs/cloudflare-compat.md. Existing Wrangler projects build without modification, and Durable Object classes use identical syntax and semantics, including state.storage operations and RPC methods.

How does celld handle Durable Object state persistence?

Each Durable Object instance (cell) maintains state in an isolated SQLite database managed by crates/celld/storage.rs. The JavaScript harness in crates/celld/js/harness.js exposes this through the standard DurableObjectStorage interface, providing transactional consistency for get, put, and delete operations. State automatically replicates to the configured S3-compatible bucket.

What infrastructure is required to run celld?

celld requires only an S3-compatible object storage bucket for deployment artifacts and cell state replication. Nodes run as standalone binaries that embed V8 and communicate directly with the storage backend. No Kubernetes, consensus clusters, or Cloudflare-specific services are necessary, though esbuild must be available on the deployment host's PATH.

How does celld ensure single-owner semantics without consensus protocols?

The system uses object-storage compare-and-swap operations to establish cell ownership, as implemented in crates/celld/protocol.rs. This guarantees that at most one node can own a Durable Object cell at any time, providing the same execution guarantees as Cloudflare's infrastructure without requiring Raft, Paxos, or other distributed consensus mechanisms.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →