# Architectural Differences Between celld and Cloudflare Durable Objects: A Technical Deep Dive

> Explore the architectural differences between celld and Cloudflare Durable Objects. Understand how celld offers a self-hosted alternative with SQLite and S3, contrasting with Cloudflare's managed edge service.

- Repository: [Deno/celld](https://github.com/denoland/celld)
- Tags: deep-dive
- Published: 2026-08-09

---

**celld is a self-hosted daemon that replicates Cloudflare's Durable Objects programming model using per-object SQLite databases and S3-compatible object storage for coordination, whereas Cloudflare Durable Objects run as a fully managed service on Cloudflare's edge network with proprietary storage and coordination mechanisms.**

The `denoland/celld` repository provides an open-source implementation of the Cloudflare Workers runtime and Durable Objects (DO) model designed for self-hosted deployment. While both platforms expose the same developer-facing API for stateful serverless computing, they differ fundamentally in storage architecture, coordination mechanisms, and operational control. Understanding these architectural differences between celld and Cloudflare Durable Objects is essential for teams deciding between managed convenience and infrastructure sovereignty.

## Deployment and Ownership Models

### Self-Hosted Binary vs. Managed Edge Service

**celld** operates as a binary you install locally or inside a container. Each node embeds V8 and executes Wrangler bundles directly on your hardware, giving you complete control over the runtime environment. You manage the binary lifecycle, hardware or VM provisioning, and network configuration.

In contrast, **Cloudflare Durable Objects** run exclusively on Cloudflare's edge network as a managed service. You deploy code to Cloudflare's infrastructure without hosting the runtime yourself, sacrificing control for operational simplicity.

## State Storage Architecture

### SQLite-Per-Object vs. Proprietary Storage

The most significant architectural divergence lies in persistence implementation. In celld, every Durable Object is backed by an **isolated SQLite database** stored as a single file per object. This design is implemented in the core runtime and ensures that state is physically separated by object identity.

Cloudflare Durable Objects store state in Cloudflare's internal proprietary storage layer. The replication, durability, and failover mechanisms are handled transparently by the platform without exposing storage implementation details to developers.

### Replication via Object Storage CAS

celld replicates state to an **S3-compatible bucket** (or any object store) using a simple compare-and-swap protocol defined in [`crates/celld/protocol.rs`](https://github.com/denoland/celld/blob/main/crates/celld/protocol.rs). Every change is written to the bucket, and ownership transitions rely on this object storage layer as the single source of truth.

Cloudflare's native implementation manages replication internally using their global edge network infrastructure, requiring no configuration or visibility into the replication protocol from users.

## Coordination and Consensus

### Decentralized Ownership Election

celld implements a **decentralized coordination model** with no central control plane or consensus algorithm. Nodes elect an owner for each object exclusively via **object-storage CAS** operations. When a node wants to own an object, it attempts to write a lease to the bucket; if successful, it becomes the exclusive handler for that object's requests.

Cloudflare automatically routes requests to the current owner through their internal edge network, running proprietary coordination and lease mechanisms invisible to developers.

## Scalability Characteristics

### Natural Sharding by Construction

Because each object in celld lives in its own SQLite file, the system **shards by construction**. There is no single shared database that can become a bottleneck, allowing horizontal scalability across nodes simply by distributing objects.

Cloudflare handles sharding internally and invisibly. Developers write code as if accessing a single global state, while the platform manages the physical distribution of objects across their edge infrastructure.

## Execution Environment and Compatibility

### V8 Isolate Runtime Limitations

celld executes Workers code in a V8 isolate that processes Wrangler bundles, but the runtime includes only the core Worker surface—**fetch, RPC, assets, and DO bindings**. According to [`docs/cloudflare-compat.md`](https://github.com/denoland/celld/blob/main/docs/cloudflare-compat.md), features such as KV, R2, Cron, and platform-specific services are **not implemented**.

Cloudflare Durable Objects provide access to the full Cloudflare platform stack, including KV, R2, D1, Cron triggers, AI services, and other proprietary bindings.

## Network Topology and Security

### Peer-to-Peer HTTP with HMAC Authentication

Communication between celld nodes occurs over plain HTTP with **HMAC-authenticated, clock-bounded** requests implemented in [`crates/celld/peer_auth.rs`](https://github.com/denoland/celld/blob/main/crates/celld/peer_auth.rs). You must expose peer ports on a private network or encrypted overlay (such as WireGuard) to secure inter-node traffic.

Cloudflare routes traffic through their internal edge network, handling TLS termination, DDoS protection, and geographic routing automatically without requiring network configuration from developers.

## Practical Implementation Examples

### Defining a Durable Object in celld

The following code works identically on both platforms, but celld stores the state in SQLite and replicates it via the configured bucket:

```javascript
export class Counter {
  async fetch(request, env) {
    const url = new URL(request.url);
    if (url.pathname === "/inc") {
      await env.storage.put("value", (await env.storage.get("value")) + 1);
      return new Response("incremented");
    }
    const value = await env.storage.get("value");
    return new Response(`value = ${value}`);
  }
}

// wrangler.jsonc configuration
{
  "durable_objects": {
    "bindings": [{ "name": "COUNTER", "class_name": "Counter" }]
  }
}

```

### Deploying and Running celld Nodes

Deploy your worker bundle and start nodes using the CLI as described in the project's [`README.md`](https://github.com/denoland/celld/blob/main/README.md):

```bash

# Deploy the worker bundle to the bucket

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

# Start a node (repeat on multiple machines)

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

```

### Accessing Objects from Clients

The RPC surface remains compatible with Cloudflare's API, with celld's runtime handling the underlying transport:

```javascript
const stub = COUNTER.idFromName("my-counter").getStub();
await stub.fetch("https://example.com/inc");
const resp = await stub.fetch("https://example.com/");
console.log(await resp.text()); // "value = 42"

```

## Summary

- **celld** provides a self-hosted alternative to Cloudflare Durable Objects using per-object SQLite files and S3-compatible storage for state management.
- State replication relies on a **compare-and-swap protocol** ([`crates/celld/protocol.rs`](https://github.com/denoland/celld/blob/main/crates/celld/protocol.rs)) rather than proprietary infrastructure.
- **No central control plane** exists in celld; coordination happens through object-storage operations, unlike Cloudflare's managed routing.
- Each object maintains **isolated SQLite storage**, creating natural sharding without shared database bottlenecks.
- The runtime supports core Durable Object APIs but **lacks Cloudflare-specific services** like KV, R2, and Cron according to [`docs/cloudflare-compat.md`](https://github.com/denoland/celld/blob/main/docs/cloudflare-compat.md).
- Nodes communicate via **HMAC-authenticated HTTP** ([`crates/celld/peer_auth.rs`](https://github.com/denoland/celld/blob/main/crates/celld/peer_auth.rs)) requiring manual network security configuration.

## Frequently Asked Questions

### Can I migrate existing Cloudflare Durable Objects code to celld without modifications?

Yes, celld implements the same JavaScript API surface for Durable Objects, including `fetch` handlers and `env.storage` methods. However, you must remove or polyfill dependencies on Cloudflare-specific services like KV, R2, or D1 that are not implemented in the open-source runtime. Review the compatibility matrix in [`docs/cloudflare-compat.md`](https://github.com/denoland/celld/blob/main/docs/cloudflare-compat.md) before migrating production workloads.

### How does celld handle failover if a node crashes?

celld uses an **event-driven replication model** where every state change is written to the configured S3-compatible bucket. When a node crashes, another node can take over ownership by reading the latest SQLite snapshot from the bucket and acquiring a new lease via the CAS protocol. This design eliminates the need for a separate join service or complex consensus algorithms.

### What are the security implications of running celld on my own infrastructure?

You are responsible for securing the **peer-to-peer communication layer** between nodes. The implementation in [`crates/celld/peer_auth.rs`](https://github.com/denoland/celld/blob/main/crates/celld/peer_auth.rs) provides HMAC authentication and clock-bounded request validation, but you must expose peer ports on private networks or encrypted overlays like WireGuard. Unlike Cloudflare's managed service, TLS termination and DDoS protection are not handled automatically and require manual configuration.

### Does celld support horizontal scaling across multiple regions?

Yes, because each Durable Object is an independent SQLite file replicated to object storage, you can run celld nodes in multiple geographic regions. Objects automatically migrate to whichever node requests ownership, limited only by the latency of your object storage backend. This architecture avoids the single-database bottleneck that limits traditional stateful systems.