How Celld Implements Cell Hibernation and Wake-Up for Resource Reduction
Celld minimizes infrastructure costs by moving idle Durable Object cells from active memory to external storage as SQLite snapshots, then automatically restoring them when requests or scheduled alarms demand execution.
Celld is an open-source runtime for Durable Objects that implements aggressive resource management to reduce operational overhead. The cell hibernation and wake-up system allows the platform to transparently persist dormant cells to cheap object storage and resurrect them on demand, eliminating the memory and CPU tax of idle workloads.
The Hibernation Lifecycle
Initiating Hibernation via RuntimeManager
When a cell becomes idle or its next alarm is far in the future, Celld initiates shutdown through RuntimeManager::stop_cell (lines 52-86 in crates/celld/runtime.rs). This method accepts a hibernate flag that determines whether the cell state should be preserved for later restoration.
If hibernation is requested, the runtime invokes RuntimeManager::hibernate (lines 216-218), which delegates to Replication::hibernate in crates/celld/replication.rs. This creates a snapshot file with the .hibernated extension containing the cell’s complete SQLite database state.
// Stop a cell and trigger hibernation
await runtime_manager
.stop_cell("my-do:1234", epoch, /*hibernate=*/ true, /*preserve_local=*/ false)
.await;
Creating and Storing Snapshots
The Replication::hibernate method generates the hibernation artifact by copying the active SQLite database to a sibling file ending in .hibernated. This snapshot is then uploaded to an S3-compatible bucket, after which the original local file is deleted to reclaim disk space.
According to the source code in crates/celld/storage.rs (lines 9-10), the system simultaneously closes the database connection and clears the in-process connection map. This ensures the cell no longer holds file descriptors or memory buffers, completing the resource release phase.
Releasing Runtime Resources
Hibernation frees three critical resource categories:
- Memory: The isolate and its heap are shut down completely
- File descriptors: Database connections close, dropping OS-level handles
- CPU: The event loop stops processing tasks for the cell
The connection map in storage.rs tracks active database handles; clearing this map during hibernation ensures zero lingering resource claims.
The Wake-Up Process
Background Wake Monitoring
A persistent background task defined in crates/logic/wake.rs continuously scans for cells requiring activation. The wake logic monitors two triggers:
- Alarm triggers: Cells with scheduled alarms that have become due
- Request triggers: Incoming HTTP requests targeting hibernated cells via
fetch_cell
When either condition is met, the wake task invokes wake_cell logic to begin restoration.
Restoring from Snapshot
The restoration process reverses hibernation through Replication::restore (located in crates/celld/replication.rs). This method:
- Downloads the
.hibernatedsnapshot from the bucket - Renames the file back to the active database name
- Reopens the SQLite connection
- Spawns a new isolate for the cell
The cell resumes execution exactly where it left off, with its full state intact. Once restored, fetch_cell operations proceed normally, as shown in this automatic wake-up pattern:
// Automatically triggers Replication::restore if cell is hibernated
let response = runtime_manager
.fetch_cell(
"my-do:1234".into(),
None,
RuntimeFetch { url, method, body, headers, request_id: None },
None,
)
.await?;
Implementation Details
The hibernation system relies on tight coordination between four core components:
crates/celld/runtime.rs: Orchestrates the stop/hibernate/fetch lifecycle and routes requests to active or dormant cellscrates/celld/replication.rs: Handles physical snapshot creation (hibernate) and restoration (restore) operationscrates/celld/storage.rs: Manages the connection map that must clear during hibernation to release resourcescrates/logic/wake.rs: Implements the background scanner that detects when hibernated cells require wake-up
The bucket storage enforces size ceilings on snapshots, preventing unbounded growth of hibernation artifacts while maintaining durability guarantees.
Summary
- Celld implements cell hibernation and wake-up to move idle Durable Objects from expensive runtime memory to cheap object storage
RuntimeManager::stop_cellinitiates hibernation by creating.hibernatedsnapshots viaReplication::hibernatestorage.rsclears connection maps during hibernation, freeing memory and file descriptors completelylogic/wake.rsmonitors alarms and requests to trigger wake-up automaticallyReplication::restoreresurrects cells by downloading snapshots and recreating isolates, preserving exact execution state
Frequently Asked Questions
What triggers cell hibernation in Celld?
Hibernation triggers when the scheduler determines a cell is idle or when an alarm is scheduled far enough in the future to justify the snapshot overhead. The RuntimeManager::stop_cell method receives a boolean hibernate flag that initiates the process, typically set by the scheduler when resource reclamation outweighs the cost of future restoration.
How does Celld ensure data integrity during hibernation?
Data integrity relies on SQLite’s atomic copy mechanism and the .hibernated file format. Replication::hibernate creates a complete point-in-time snapshot of the database file before upload. The wake process in Replication::restore renames this snapshot back to the active database name only after successful download, ensuring the cell resumes with exactly the state it held when hibernated.
What storage backend does Celld use for hibernated cells?
Celld uses any S3-compatible object storage bucket configured in the replication layer. The Replication struct abstracts the storage client, allowing the system to upload .hibernated snapshots to services like AWS S3, MinIO, or Cloudflare R2. The bucket enforces configurable size ceilings to prevent storage exhaustion.
How long does wake-up take for a hibernated cell?
Wake-up latency depends on network download time for the SQLite snapshot and isolate initialization overhead. The process involves downloading the .hibernated file from the bucket, renaming it to the active database path, reopening the connection in storage.rs, and spawning a new isolate. This typically adds hundreds of milliseconds to the first request compared to an active cell, but subsequent requests perform at normal speed.
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:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →