Sandbox memory snapshots

🌱 Sandbox memory snapshots are in early preview, pre-beta.

Sandbox memory snapshots are copies of a Sandbox’s entire state, both in memory and on the filesystem. These Snapshots can be restored later to create a new Sandbox, which is an exact clone of the original Sandbox.

To snapshot a Sandbox, create it with _experimental_enable_snapshot set to True, and use the _experimental_snapshot method, which returns a SandboxSnapshot object:

image = modal.Image.debian_slim().apt_install("curl", "procps")
app = modal.App.lookup("sandbox-snapshot", create_if_missing=True)

with modal.enable_output():
    sb = modal.Sandbox.create(
        "python3", "-m", "http.server", "8000",
        app=app, image=image, _experimental_enable_snapshot=True
    )

print(f"Performing snapshot of {sb.object_id} ...")
snapshot = sb._experimental_snapshot()

Create a new Sandbox from the returned SandboxSnapshot with Sandbox._experimental_from_snapshot:

print(f"Restoring from snapshot {sb.object_id} ...")
sb2 = modal.Sandbox._experimental_from_snapshot(snapshot)

print("Let's see that the http.server is still running...")
p = sb2.exec("ps", "aux")
print(p.stdout.read())

# Talk to snapshotted sandbox http.server
p = sb2.exec("curl", "http://localhost:8000/")
reply = p.stdout.read()
print(reply)  # <!DOCTYPE HTML><html lang...

The new Sandbox will be a duplicate of your original Sandbox. All running processes will still be running, in the same state as when they were snapshotted, and any changes made to the filesystem will be visible.

You can retrieve the ID of any Sandbox Snapshot with snapshot.object_id . To restore from a snapshot by ID, first rehydrate the Snapshot with SandboxSnapshot.from_id and then restore from it:

snapshot_id = snapshot.object_id
# ... save the Sandbox ID (sb-123abc) for later
# sometime in the future...
snapshot = modal.SandboxSnapshot.from_id(snapshot_id)
sandbox = modal.Sandbox._experimental_from_snapshot(snapshot)

Note that these methods are experimental, and we may change them in the future.

Re-snapshotting

Modal supports creating a new snapshot from a restored Sandbox snapshot. To maintain the snapshot’s expiration window, the new snapshot inherits the expiration of its parent.

Continuing from the example code above, we demonstrate re-snapshotting:

# Add a file to the snapshotted sandbox
p = sb2.exec("touch", "/foo")
p.wait()

snapshot2 = sb2._experimental_snapshot()
print(f"Restoring from new snapshot {sb.object_id} ...")
sb3 = modal.Sandbox._experimental_from_snapshot(snapshot2)
# Talk to re-snapshotted sandbox http.server
p = sb3.exec("curl", "http://localhost:8000/")
reply = p.stdout.read()
print(reply)  # Shows the new 'foo' directory in the HTML listing.

Limitations

Currently, Sandbox Snapshots will expire 7 days after creation.

Open TCP connections will be closed automatically when a Snapshot is taken, and will need to be reopened when the Snapshot is restored.

Snapshotting a sandbox will currently cause it to terminate. We intend to remove this limitation soon.

Sandboxes created with _experimental_enable_snapshot=True or restored from Snapshots cannot run with GPUs.

It is not possible to snapshot a sandbox while a Sandbox.exec command is still running. Furthermore, any background processes launched by a call to Sandbox.exec will not be properly restored after a snapshot.