Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
72 changes: 72 additions & 0 deletions src/content/changelog/containers/2026-03-26-snapshots.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
---
title: Snapshot and restore Container state
description: Persist point-in-time container filesystem with experimental snapshot APIs.
products:
- containers
date: 2026-03-26
---

import { TypeScriptExample, WranglerConfig } from "~/components";

[Containers](/containers/) now support experimental snapshot APIs for saving and restoring point-in-time filesystem state. Create a snapshot first, then pass it back to `start()` to restore files after container sleep, restart, or handoff to another Durable Object.

Turn on the `experimental` [compatibility flag](/workers/configuration/compatibility-flags/) before you use snapshot APIs:

<WranglerConfig>

```toml
compatibility_flags = ["experimental"]
```

</WranglerConfig>

You can snapshot a single directory with `snapshotDirectory()` or the full container with `snapshotContainer()`. The example uses the [Container class](/containers/container-package/). Create snapshots from a container that is already running:

<TypeScriptExample filename="src/index.ts">

```ts
import { Container } from "@cloudflare/containers";

export class MyContainer extends Container {
async saveSnapshots() {
const directorySnapshot = await this.ctx.container.snapshotDirectory({
dir: "/app/foo",
});

const containerSnapshot = await this.ctx.container.snapshotContainer({});

await this.ctx.storage.put("directorySnapshot", directorySnapshot);
await this.ctx.storage.put("containerSnapshot", containerSnapshot);
}
}
```

</TypeScriptExample>

Later, if you saved both snapshot types, load the saved snapshot handles and restore them with `start()`:

<TypeScriptExample filename="src/index.ts">

```ts
import { Container } from "@cloudflare/containers";

export class MyContainer extends Container {
async restoreSnapshots() {
const directorySnapshot =
await this.ctx.storage.get<any>("directorySnapshot");
const containerSnapshot =
await this.ctx.storage.get<any>("containerSnapshot");

this.ctx.container.start({
containerSnapshot,
directorySnapshots: [{ snapshot: directorySnapshot }],
});
}
}
```

</TypeScriptExample>

Snapshots are immutable. Directory snapshots can be restored to a different `mountPoint`. You can restore multiple directory snapshots in one `start()` call, but only one container snapshot.

For more information, refer to [Snapshots](/containers/platform-details/snapshots/) and [Durable Object Container](/durable-objects/api/container/).
6 changes: 2 additions & 4 deletions src/content/docs/containers/faq.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,9 @@ See [image management documentation](/containers/platform-details/image-manageme

## Is disk persistent? What happens to my disk when my container sleeps?

All disk is ephemeral. When a Container instance goes to sleep, the next time
it is started, it will have a fresh disk as defined by its container image.
All disk is ephemeral by default. When a Container instance goes to sleep, the next time it starts, it uses a fresh disk from the container image.

Persistent disk is something the Cloudflare team is exploring in the future, but
is not slated for the near term.
If you need point-in-time filesystem state, create and restore an experimental snapshot. Snapshots are immutable, so later file changes require a new snapshot. For more information, refer to [Snapshots](/containers/platform-details/snapshots/).

## What happens if I run out of memory?

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,12 +98,11 @@ When a container instance is going to be shut down, it is sent a `SIGTERM` signa
and then a `SIGKILL` signal after 15 minutes. You should perform any necessary
cleanup to ensure a graceful shutdown in this time.

#### Persistent disk
#### Use snapshots

All disk is ephemeral. When a Container instance goes to sleep, the next time
it is started, it will have a fresh disk as defined by its container image.
Persistent disk is something the Cloudflare team is exploring in the future, but
is not slated for the near term.
All disk is ephemeral by default. When a Container instance goes to sleep, the next time it starts, it uses a fresh disk from the container image.

If you need point-in-time filesystem state, create and restore an experimental snapshot. Snapshots are immutable, so later file changes require a new snapshot. For more information, refer to [Snapshots](/containers/platform-details/snapshots/).

## An example request

Expand Down
181 changes: 181 additions & 0 deletions src/content/docs/containers/platform-details/snapshots.mdx
Original file line number Diff line number Diff line change
@@ -0,0 +1,181 @@
---
title: Use snapshots
pcx_content_type: how-to
sidebar:
order: 55
description: Persist container filesystem across restarts.
---

import { TypeScriptExample, WranglerConfig } from "~/components";

Snapshots let you save point-in-time filesystem state from a running [Container](/containers/). The examples on this page use the [Container class](/containers/container-package/).

:::caution[Experimental]
Snapshot APIs require the `experimental` [compatibility flag](/workers/configuration/compatibility-flags/). These APIs may change in backward-incompatible ways.
:::

## Turn on the compatibility flag

Add `experimental` to your Worker's Wrangler configuration before you use snapshot APIs:

<WranglerConfig>

```toml
compatibility_date = "$today"
compatibility_flags = ["experimental"]
```

</WranglerConfig>

## Choose a snapshot type

Use `snapshotDirectory()` to capture one directory. Use `snapshotContainer()` to capture the full container filesystem.

Both snapshot types are immutable. If you restore a snapshot and then change files, create a new snapshot to persist those changes.

- You can restore multiple directory snapshots in one `start()` call.
- You can restore only one container snapshot in one `start()` call.
- You can restore directory snapshots on top of a container snapshot.
- Snapshot handles are plain data objects, so you can store them and restore them later, even from another Durable Object.

## Create a directory snapshot

Use `snapshotDirectory()` to capture the current contents of a directory in a running container:

<TypeScriptExample filename="src/index.ts">

```ts
import { Container } from "@cloudflare/containers";

export class MyContainer extends Container {
async saveWorkspace() {
return await this.ctx.container.snapshotDirectory({
dir: "/app/workspace",
name: "workspace-checkpoint",
});
}
}
```

</TypeScriptExample>

The `dir` value must be an absolute path. The API returns a serializable snapshot handle that you can store and restore later.

## Create a container snapshot

Use `snapshotContainer()` to capture the full container filesystem:

<TypeScriptExample filename="src/index.ts">

```ts
import { Container } from "@cloudflare/containers";

export class MyContainer extends Container {
async saveContainer() {
return await this.ctx.container.snapshotContainer({
name: "before-upgrade",
});
}
}
```

</TypeScriptExample>

The API returns a serializable snapshot handle that you can store and restore later.

## Restore snapshots

First, create snapshots from a container that is already running. You can store the returned handles in Durable Object storage and use them later:

<TypeScriptExample filename="src/index.ts">

```ts
import { Container } from "@cloudflare/containers";

export class MyContainer extends Container {
async saveSnapshots() {
const directorySnapshot = await this.ctx.container.snapshotDirectory({
dir: "/app/foo",
});

const containerSnapshot = await this.ctx.container.snapshotContainer({});

await this.ctx.storage.put("directorySnapshot", directorySnapshot);
await this.ctx.storage.put("containerSnapshot", containerSnapshot);
}
}
```

</TypeScriptExample>

Later, if you saved both snapshot types, load the saved snapshot handles and pass them to `this.ctx.container.start()` when you start another container:

<TypeScriptExample filename="src/index.ts">

```ts
import { Container } from "@cloudflare/containers";

export class MyContainer extends Container {
async restoreSnapshots() {
const directorySnapshot =
await this.ctx.storage.get<any>("directorySnapshot");
const containerSnapshot =
await this.ctx.storage.get<any>("containerSnapshot");

this.ctx.container.start({
containerSnapshot,
directorySnapshots: [{ snapshot: directorySnapshot }],
});
}
}
```

</TypeScriptExample>

If you do not set `mountPoint`, the directory snapshot is restored to the same path that was snapshotted. You can also restore it to a different path:

<TypeScriptExample filename="src/index.ts">

```ts
import { Container } from "@cloudflare/containers";

export class MyContainer extends Container {
async restoreWorkspaceSnapshot() {
const directorySnapshot =
await this.ctx.storage.get<any>("directorySnapshot");

if (!directorySnapshot) {
return;
}

this.ctx.container.start({
directorySnapshots: [
{
snapshot: directorySnapshot,
mountPoint: "/app/restored-workspace",
},
],
});
}
}
```

</TypeScriptExample>

## Understand restore behavior

- Directory snapshots cannot be restored to `/`.
- You can snapshot `/`, but you must restore it to a subdirectory by setting `mountPoint`.
- Nested directory snapshots restore in depth order. If you restore snapshots to `/app` and `/app/data`, `/app` is always restored first.
- Directory snapshots can overlay files from a container snapshot.

## Understand retention

Snapshots currently have an implicit 90-day time-to-live. Each restore refreshes that time-to-live.

You cannot set a custom time-to-live yet.

## Related resources

- [Durable Object Container](/durable-objects/api/container/) - Full `ctx.container` API reference
- [Lifecycle of a Container](/containers/platform-details/architecture/) - Understand startup, sleep, and shutdown behavior
Loading
Loading