Skip to content

Caches and snapshots

Save installed software or files so another sandbox can start from them:

from sandweave import Sandbox

with Sandbox() as env:
    env.files.write_text("/workspace/note.txt", "saved state")
    baseline = env.cache("my-workbench")

with Sandbox(cache="my-workbench") as env:
    print(env.files.read_text("/workspace/note.txt"))

Caches save filesystem state by default. A restore starts fresh processes with independent writable state. It also restores the template's services and controls, so you do not need to specify the template again.

Saving first captures into the worker's local directory, then publishes a copy under its persistent snapshot storage. Background verification removes the local staging copy after the published files pass verification. Restores use the published files even while verification is pending, so cleanup does not interrupt them. Failed verification retains staging for recovery; diagnostic --local-only captures are also retained.

Filesystem capture pauses the sandbox for a consistent cut of all its persistent mounts, then resumes it before publication and checksum verification. Runtime 2026.09.26.5 batches archive writes and reuses copy buffers, reducing overhead for filesystems with many small files. The archive format is unchanged.

Exports have a ten-minute no-progress limit per mount, rather than a fixed total duration. Large exports can continue while the archive grows. To change this limit, set SANDWEAVE_SNAPSHOT_STALL_TIMEOUT to positive seconds in the worker's environment before starting it; for example, 1800 allows thirty minutes without output progress. This setting applies to filesystem capture, including caches, and does not change transport or restore startup deadlines.

Restore startup timeout

Use startup_timeout to allow a large snapshot more time to restore:

env = Sandbox(snapshot=baseline, startup_timeout=1800)

The default is 300 seconds. This is one total creation budget, shared by boot staging, unpacking all saved mounts (including Docker and containerd), and service readiness. Starting a new restore phase does not reset it. Since 0.2.39, these phases respect the requested budget instead of imposing separate 300-second staging and 600-second per-mount limits.

The same option works with cache=, Pool(..., startup_timeout=1800), and Weave targets. For the CLI:

sandweave create --cache my-workbench --startup-timeout 1800

Upgrade the worker to 0.2.39 or newer; no image or engine rebuild is needed. Timeout or cancellation aborts the incomplete restore and retains the saved snapshot for retry. SANDWEAVE_SNAPSHOT_STALL_TIMEOUT still controls saves only.

Pin a particular version

A cache name can point to a newer revision later. Use the returned reference to reuse exactly the version you saved:

with Sandbox(cache=baseline) as env:
    print(env.files.read_text("/workspace/note.txt"))

A missing cache raises CacheMiss. It does not silently build a replacement. On a cluster, use the same cluster target when creating and restoring the cache.

Save Docker storage

The docker template starts with empty Docker and containerd storage. Images, containers and named volumes are included when saving its filesystem:

with Sandbox(template="docker") as env:
    env.run("docker pull busybox:1.37.0", timeout=180, check=True)
    baseline = env.cache("docker-ready")

with Sandbox(cache="docker-ready") as env:
    print(env.run("docker image ls", check=True).stdout)

Each restore has independent storage. A filesystem restore starts fresh processes; use docker start for saved containers without an automatic restart policy. The saved files are crash-consistent: application buffers held only in RAM are not included. Memory checkpoints also save supported running processes.

Custom templates can set runtime_options.docker_data = true to create the same checkpointed storage mounts. The Docker template enables this by default. Its overlay2 driver needs these separate writable filesystems; a custom template that disables them must provide compatible storage for its driver. docker_archive optionally seeds those mounts from an immutable installation asset on first launch; restoring a checkpoint uses its saved data and does not require or reimport that archive.

Reuse setup automatically

from sandweave import Sandbox

with Sandbox(setup="./install-tools.sh", cache_key="tools-build") as env:
    print(env.run("python --version").stdout)

Provide your own setup script. cache_key prepares a recipe and reuses its saved result when the template, script, and declared inputs match. A change to those inputs creates a new revision. cache loads an existing saved state directly.

Pause and resume

with Sandbox() as env:
    env.pause()
    env.resume()

Pause keeps the same environment resident, including memory and GPU state. It does not release the runtime's memory reservation or save a durable checkpoint.

Checkpoint memory

from sandweave import Sandbox

with Sandbox() as env:
    env.files.write_text("/workspace/note.txt", "saved state")
    checkpoint = env.snapshot(state="memory")
    if checkpoint.verify()["status"] != "passed":
        raise RuntimeError("Checkpoint verification failed")

with Sandbox(snapshot=checkpoint) as restored:
    print(restored.files.read_text("/workspace/note.txt"))

A supported gVisor memory snapshot saves process and kernel state as well as files. Verification can run asynchronously; the example checks it before attempting a restore. External services and shared volumes do not roll back.

During gVisor snapshot publication and transfer, Sandweave reuses checksums for files whose recorded identity and timestamps still match. New copies are checked before publication. Calling checkpoint.verify() explicitly rechecks the bytes.

Save before stopping

env = Sandbox()
saved = env.stop()
env.close()

with Sandbox(snapshot=saved) as restored:
    print(restored.run("python --version").stdout)

stop() saves before releasing the runtime. A failed save keeps the source running. Use terminate() when you want to discard unsaved state instead.

GPU and native runtime support

GPU filesystem caches start fresh GPU processes. Ordinary live graphics state cannot be restored. CUDA-only memory restoration is experimental and needs experimental_gpu_live=True at capture and restore.

Native Apptainer supports filesystem caches, but not memory snapshots. See resources for runtime differences.