How celld Handles Deployment Rollbacks Using Versioned Manifests

celld implements atomic deployment rollbacks by storing immutable versioned manifests in object storage and moving a current pointer to a previous version, enabling instant reversion to older code and SQLite state without data loss.

The denoland/celld project provides a durable compute platform that treats every deployment as an immutable artifact. Understanding how celld deployment rollbacks work requires examining its versioned manifest architecture, where each release is stored as an immutable JSON document and a single pointer determines which version nodes execute.

Immutable Versioned Manifest Storage

Each deployment in celld is stored as an immutable, version-qualified manifest in shared object storage. According to the protocol definition in crates/celld/protocol.rs (lines 10-15), manifests are written to the path:


deploy/<script>/<version>/manifest.json

This immutability guarantee ensures that historical deployment artifacts remain intact indefinitely. The manifest contains the complete deployment specification, including module lists, static assets, and durable object class definitions. Because the file is never modified after creation, rolling back to any previous version simply requires referencing its existing manifest path.

The Current Pointer and Atomic Compare-and-Swap

Rather than overwriting deployment data, celld maintains a current pointer in the object storage bucket that references the active version's manifest. When a new deployment succeeds, celld updates this pointer to reference the new version's manifest path, a process handled in crates/celld/deploy.rs.

A rollback operation performs an atomic compare-and-swap on this pointer, moving it from the current version to a previous version's manifest path. This atomic operation guarantees that all nodes observe the same version simultaneously, eliminating race conditions during rollback events. The pointer update is transactional—either all nodes see the new (old) version, or none do.

Storage Layer Rollback Handling

The storage layer treats rollback operations as first-class transactional actions. In crates/celld/storage.rs (lines 1132-1134), the action handling logic specifically recognizes the "rollback" string as a valid operation, returning Ok(None) upon successful completion:

// Storage action handling in storage.rs
match action {
    "rollback" => Ok(None),
    // ... other actions like commit
}

This implementation ensures that pointer rewinds are handled consistently with other storage transactions, maintaining data integrity during version reversion operations.

Runtime Manifest Loading and State Restoration

When celld nodes start up, they read the manifest referenced by the current pointer to configure their runtime environment. The fleet initialization code in crates/celld/fleet.rs (lines 371-374) deserializes this manifest:

// Fleet initialization loads the current manifest
let manifest = load_manifest_from_pointer(&current_pointer)
    .await
    .expect("Failed to load deployment manifest");

If the pointer references an older version due to a rollback, the node automatically fetches the corresponding manifest and restores the associated SQLite snapshots from object storage. This process requires no manual intervention—nodes detect the pointer change, load the previous code modules, and resume execution with the historical state data.

Implementing a Rollback in celld

You can trigger a rollback programmatically using the storage API or via the CLI. Both methods utilize the same atomic compare-and-swap mechanism implemented in the storage layer.

Programmatic Rollback

To rollback programmatically, construct a pointer to the target version and perform an atomic swap:

use celld::storage::Bucket;
use celld::protocol::Pointer;

// Initialize bucket connection
let bucket = Bucket::new("s3://my-cells-bucket");

// Create pointer referencing version 3 manifest
let rollback_pointer = Pointer {
    prefix: "deploy/my-worker/3".to_string(),
    // additional fields omitted for brevity
};

// Atomically update current pointer
bucket.compare_and_swap_pointer("current", &rollback_pointer)?
    .expect("Rollback completed successfully");

CLI-Based Rollback

The command-line interface defined in crates/celld/main.rs provides a convenience flag for rollbacks:

celld deploy . \
  --bucket s3://my-cells-bucket \
  --rollback-version 3

This command internally constructs the appropriate pointer path and executes the compare-and-swap operation against the current pointer.

Summary

  • Immutable manifests: Every deployment is stored permanently at deploy/<script>/<version>/manifest.json, ensuring historical versions remain accessible for rollbacks.
  • Pointer indirection: A current pointer in object storage determines which version nodes execute, enabling instant version switching without data migration.
  • Atomic updates: Rollbacks use compare-and-swap operations to guarantee consistent version visibility across all nodes in the fleet.
  • Automatic state restoration: Nodes automatically load SQLite snapshots associated with the target version when processing a rollback.
  • Transactional safety: The storage layer treats "rollback" as a native action type, ensuring operational consistency with other storage transactions.

Frequently Asked Questions

How does celld ensure data consistency during a rollback?

celld ensures consistency through immutable manifests and atomic pointer updates. Because manifests in crates/celld/protocol.rs are never modified after creation, and the current pointer update uses a compare-and-swap operation, all nodes transition to the previous version simultaneously without risk of split-brain scenarios or partial deployments.

What happens to SQLite data when rolling back to a previous version?

When the current pointer moves to an older version, nodes automatically restore the SQLite snapshots associated with that version's manifest. These snapshots are stored alongside the manifests in object storage, allowing the runtime in crates/celld/fleet.rs to reconstruct the exact database state that existed during the target deployment.

Can rollbacks be performed to any previous version?

Yes. Since celld stores every deployment as an immutable artifact at deploy/<script>/<version>/manifest.json, you can rollback to any existing version by updating the current pointer to reference that specific version path. There is no limit on how far back you can roll, provided the manifest and its associated snapshots remain in storage.

Is the rollback operation reversible?

Yes. Because celld never deletes or modifies versioned manifests, you can roll forward again by moving the current pointer back to a newer version. This effectively acts as a "roll-forward" operation, restoring the system to the more recent deployment state using the same atomic pointer mechanism.

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 →