# How Celld Implements Cell Hibernation and Wake-Up for Resource Reduction

> Learn how celld implements cell hibernation and wake-up. It moves idle Durable Object cells to external storage as SQLite snapshots to reduce resource usage and restores them when needed.

- Repository: [Deno/celld](https://github.com/denoland/celld)
- Tags: internals
- Published: 2026-08-10

---

**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`](https://github.com/denoland/celld/blob/main/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`](https://github.com/denoland/celld/blob/main/crates/celld/replication.rs). This creates a snapshot file with the `.hibernated` extension containing the cell’s complete SQLite database state.

```rust
// 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`](https://github.com/denoland/celld/blob/main/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`](https://github.com/denoland/celld/blob/main/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`](https://github.com/denoland/celld/blob/main/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`](https://github.com/denoland/celld/blob/main/crates/celld/replication.rs)). This method:

1. Downloads the `.hibernated` snapshot from the bucket
2. Renames the file back to the active database name
3. Reopens the SQLite connection
4. 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:

```rust
// 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`](https://github.com/denoland/celld/blob/main/crates/celld/runtime.rs)**: Orchestrates the stop/hibernate/fetch lifecycle and routes requests to active or dormant cells
- **[`crates/celld/replication.rs`](https://github.com/denoland/celld/blob/main/crates/celld/replication.rs)**: Handles physical snapshot creation (`hibernate`) and restoration (`restore`) operations
- **[`crates/celld/storage.rs`](https://github.com/denoland/celld/blob/main/crates/celld/storage.rs)**: Manages the connection map that must clear during hibernation to release resources
- **[`crates/logic/wake.rs`](https://github.com/denoland/celld/blob/main/crates/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_cell`** initiates hibernation by creating `.hibernated` snapshots via `Replication::hibernate`
- **[`storage.rs`](https://github.com/denoland/celld/blob/main/storage.rs)** clears connection maps during hibernation, freeing memory and file descriptors completely
- **[`logic/wake.rs`](https://github.com/denoland/celld/blob/main/logic/wake.rs)** monitors alarms and requests to trigger wake-up automatically
- **`Replication::restore`** resurrects 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`](https://github.com/denoland/celld/blob/main/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.