Skip to content
crabbuildPublic

About

Native Rust framework and SDK for durable business cells and distributed applications

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

Cellar logo

Cellar

Build Rust applications around durable business cells.

Give each account, cart, room or workflow its own SQLite state. Write the business logic in Rust; Cellar handles ownership, routing, replication and recovery.

Quickstart · Write code · Architecture · Examples · Documentation

A namespace routes business names to separate cells, each with its own SQLite state.

Why cells?

A cell brings a business object's behavior and state together:

  • A cart keeps its items and checkout state in one place.
  • An account owns its balance, settings and transaction history.
  • A room coordinates participants and live connections.

Choose boundaries around data that changes together. Transactions stay within a cell; cells communicate through calls or durable events.

Quickstart

You need Rust 1.94.1 or later, Cargo, native C/C++ build tools, and curl. Run these commands from a checkout of this repository. See build guidance for local target-directory setup.

Start the counter application:

cargo run -p cellar --bin cellar --locked -- \
  dev examples/native-counter/project.json

Once the server is ready, open another terminal:

# Increment alice's counter.
curl -sS -X POST http://127.0.0.1:9876/counters/alice
# {"count":1}

# Read the same cell.
curl -sS http://127.0.0.1:9876/counters/alice
# {"count":1}

# A different name has separate state.
curl -sS http://127.0.0.1:9876/counters/bob
# {"count":0}

These values assume fresh state. Stop with Ctrl-C, restart with the same command, and read alice again: its count remains. dev watches the project and keeps local state beside its configuration under .cellar/.

Open the counter source or follow its walkthrough for routing, assets and cleanup.

Work with cells

Update a cell's state

Inside a cell handler, use its SDK context to access storage. This helper increments a counter in one transaction:

use cellar::sdk::Context;

fn increment(context: &Context) -> anyhow::Result<u64> {
    let storage = context.storage()?;
    storage.transaction_sync(|tx| {
        let count: u64 = match tx.get_json("count")? {
            Some(value) => serde_json::from_value(value)?,
            None => 0,
        };
        let next = count
            .checked_add(1)
            .ok_or_else(|| anyhow::anyhow!("counter overflow"))?;
        tx.put_json("count", &serde_json::json!(next))?;
        Ok(next)
    })
}

The storage belongs to the current cell. Cellar checks ownership and durability before releasing a successful handler response. See storage and transactions.

Call a cell by name

In a gateway handler, resolve a declared namespace and forward the request:

use cellar::sdk::{Context, Invocation, Output, Registry};

let application = Registry::new(|context: Context, invocation| {
    Box::pin(async move {
        let Invocation::Fetch(request) = invocation else {
            anyhow::bail!("expected an HTTP request");
        };
        let counter = context.namespace("COUNTERS")?.get_by_name("alice");
        Ok(Output::Http(counter.fetch(&context, request).await?))
    })
});

COUNTERS is a namespace binding declared in your project configuration. The same name finds the same cell within that namespace, even when its owner changes. The complete counter also registers its cell factory; this gateway snippet shows only request forwarding.

Use Axum or embed the runtime

cellar-axum lets you use Axum handlers, middleware and optional OpenAPI. Run the same counter in an Axum-owned HTTP server:

# Stop the earlier server before reusing port 9876.
cargo run -p cellar-axum-counter --bin axum-host --locked -- \
  127.0.0.1:9876 examples/.cellar/axum-counter

POST to /counters/alice, or open /docs for Swagger UI. The two-host example includes both hosting modes and a generated Rust client.

To own listeners, executors and node lifecycle directly, start with the embedded Node example.

How Cellar works

Four concepts

Concept Meaning
Cell Business behavior with its own durable SQLite state.
Namespace A binding used to find and call cells by name or ID.
Node A process running compiled applications and hosting cells.
Fleet Nodes sharing an object store for ownership and durable data.

Inside a node

Cellar's internal architecture: a native application uses the runtime; an actor owns the pure decision core, while adapters connect storage and fleet services to peer logs and object storage.

Applications use cellar::sdk. Inside the host, a serial actor owns the pure decision core; adapters execute effects and return completion events. The execution domain owns tasks, services and shutdown.

Arrows show component relationships. For the request lifecycle and component boundaries, see architecture and ownership.

Route to the owner

An application reaches a fleet of Cellar nodes. Nodes route calls to the owner, replicate peer logs, and share object storage.

Each cell has one authoritative owner. A request can arrive at another node; Cellar routes it to the owner. Before a replacement owner serves the cell, Cellar recovers the required state and log history.

Prove a write before replying

Cell code commits SQLite changes, Cellar proves durability through peer logs or bucket upload, and the output gate releases success.

SQLite writes are captured as LTX, the replication format. A single bucket-backed node waits for upload proof. A fleet can prove durability through peer logs before uploading to the bucket.

The output gate checks the required proof before releasing success. If a reply is lost, the caller may still have an ambiguous outcome; use an explicit idempotency and retry contract.

Explore the SDK

Pick a working example for the part you need:

Build Start here
Stored data and transactions SQL, KV, Blob
Calls between cells RPC
Background jobs Alarms, queues, workflows
Event delivery Transactional outbox, durable streams
Web applications Static assets, WebSockets
Fleet management Fleet console, FleetCare lab

See the full example catalog for more recipes. Event-delivery work and its remaining qualification gates are tracked in the implementation status.

Package and deploy

Build a package containing your compiled application:

cargo run -p cellar --bin cellar --locked -- \
  build examples/native-counter/project.json --output counter-package

The CLI can publish a package with deploy and download a verified executable with install. Run that application executable on your nodes; the generic CLI does not contain your application's factories.

Follow packaging and deployment for credentials, shared storage, installation and rollout. The distributed fleet example covers local recovery and handoff drills.

Workspace crates

Start with cellar to build an application. The other crates separate HTTP integration, fleet administration and runtime internals:

Crate Purpose
cellar Application SDK, production host and CLI
cellar-axum Axum handlers, external ingress and optional OpenAPI
cellar-admin Authenticated fleet management API and dashboard service
cellar-logic Pure runtime decisions and state transitions
cellar-native Rust values, codecs and web primitives
cellar-ltx SQLite write capture, LTX replication and restore

Documentation

Learn about Guide
Modeling cells and choosing boundaries Cell modeling
Application contexts and resource lifetimes SDK and lifetimes
Owning the runtime in your application Embedding
Running and recovering a fleet Operations, recovery
Evidence and remaining release gates Production readiness

The documentation library contains the full guides. Open the visual explorer locally for crate maps, hosting and lifetime diagrams, plus interactive request, write, recovery and shutdown flows.

Contributing

Read AGENTS.md for repository boundaries and Rust conventions. Use cargo format to format code and cargo check-layout to check module placement. The SDK CI workflow defines the full validation commands.

Cellar executes native Rust applications without a JavaScript engine. Current Cellar development uses fresh configuration and state; legacy Celld aliases and persisted-state migration are unsupported.

License

Apache-2.0. See LICENSE and NOTICE.

About

Native Rust framework and SDK for durable business cells and distributed applications

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages