Snapshots can be used to save the current disk state of a devbox, and to create new devboxes from a previous point in time. These can be used to:

  • Improve build times by snapshotting a populated build cache.
  • Roll back to a known good point in time.
  • Perform fan-out and attempt multiple approaches to a code change.

Snapshots are referenced by a random identifier and can be queried via the API. Currently only disk snapshots are supported.

When should I use a Blueprint vs. a Snapshot?

Snapshots and Blueprints both allow you to run devboxes with customizations. Blueprints are fast to boot and cacheable using Docker layers, while Snapshots are a bit slower on boot (reproducing each step taken in the devbox) but can be created quickly from an existing devbox.

Examples:

  • Blueprint: You have a coding agent that is performing a task that requires installing a specific tool. Create a blueprint with set-up steps for the tool and future devboxes will cache the installation to speed up boot and execution time.
  • Snapshot: You have a coding agent in a devbox considering 3 different ways to complete a task. Create a snapshot of the initial state of the devbox, create 3 parallel devboxes from that snapshot, collate the results, and then choose the best option to continue.
1

Identify the devbox to snapshot

First, identify a running devbox id using the dashboard or rl-cli.

$ rl devbox list --status=running

Optionally, you may want to remove any temporary files before proceeding to reduce the latency of snapshot operations.

2

Start an asynchronous disk snapshot

curl -X POST 'https://api.runloop.ai/v1/devboxes/{devbox_id}/snapshot_disk_async' \
  -H "Authorization: Bearer $RUNLOOP_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{}'
3

Poll the snapshot status

The snapshot operation runs asynchronously in the background. Poll the status until completion:

curl -X GET 'https://api.runloop.ai/v1/devboxes/disk_snapshots/{snapshot_id}/status' \
  -H "Authorization: Bearer $RUNLOOP_API_KEY"
4

Create a new devbox from the completed snapshot

Once the snapshot is complete, use the snapshot ID to launch a new devbox:

curl -X POST 'https://api.runloop.ai/v1/devboxes' \
  -H "Authorization: Bearer $RUNLOOP_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "snapshot_id": "{snapshot_id}"
  }'

Deleting Snapshots

By default, snapshots persist indefinitely and continue to incur storage costs. To optimize resource usage and costs, you can delete snapshots that are no longer needed.

Deleting a Single Snapshot

To delete a specific snapshot, use its ID:

curl --request POST \
  --url https://api.runloop.ai/v1/devboxes/disk_snapshots/{snapshot_id}/delete \
  --header 'Authorization: Bearer <token>'

Cleaning Up Old Snapshots for a Devbox

When you create multiple snapshots of the same devbox, you may want to delete older snapshots to reduce storage costs. Here’s how to keep only the latest snapshot for a specific devbox:

import time

# Create a new snapshot
new_snapshot = client.devboxes.snapshot_disk_async(devbox.id)

# Poll until snapshot is complete
while True:
    status = client.devboxes.disk_snapshots.query_status(new_snapshot.id)
    if status.status == 'complete':
        break
    elif status.status == 'error':
        print(f"Snapshot failed: {status.error_message}")
        break
    time.sleep(1)

# Get all snapshots for this devbox
snapshot_results = client.devboxes.disk_snapshots.list(devbox_id=devbox.id)

# Delete all older snapshots, keeping only the newest one
for snapshot in snapshot_results.snapshots:
    if snapshot.id != new_snapshot.id:
        client.devboxes.disk_snapshots.delete(old_snapshot.id)
        print(f"Deleted old snapshot: {old_snapshot.id}")

Be careful when deleting snapshots, as this action cannot be undone. Ensure you’re not deleting snapshots that you may need for rollback or recovery purposes.