Every time you create a new sandbox, you start with a fresh environment. If your setup involves installing dependencies, cloning repositories, or building code, it can take a while. Snapshots let you save that configured state and create new sandboxes from it, skipping the setup entirely.
With snapshots, you:
- Set up your environment once (install deps, configure tools)
- Take a snapshot to save that state
- Create future sandboxes from the snapshot - everything is already there
Snapshots persist for 7 days, so you can reuse them across multiple sessions.
Before you begin, make sure you have:
- Vercel CLI installed (
npm install -g vercel) - Node.js 22 or later
- A Vercel project to link your sandbox and generate an OIDC token
Create a new directory and install dependencies:
mkdir sandbox-snapshot-democd sandbox-snapshot-demonpm init -ynpm install @vercel/sandbox msnpm install -D @types/nodeLink your project to Vercel and pull the OIDC token for local development:
vercel linkvercel env pullThe first command connects your project to Vercel. The second creates a .env.local file with the VERCEL_OIDC_TOKEN that the SDK uses for authentication.
Create a file called index.ts and add the code below. It works in two modes so you can compare cold start vs warm start:
- First run: Creates a sandbox, installs dependencies, takes a snapshot, and saves the snapshot ID
- Second run: Creates a new sandbox from the saved snapshot and verifies dependencies are already installed
import ms from 'ms';import { Sandbox, Snapshot } from '@vercel/sandbox';import { writeFileSync, readFileSync, existsSync } from 'fs';
const SNAPSHOT_FILE = './snapshot-id.txt';const TIMING_FILE = './cold-start-time.txt';
async function main() { if (existsSync(SNAPSHOT_FILE)) { // Restore from existing snapshot const snapshotId = readFileSync(SNAPSHOT_FILE, 'utf-8').trim(); const coldStartTime = existsSync(TIMING_FILE) ? parseInt(readFileSync(TIMING_FILE, 'utf-8').trim()) : null;
console.log(`Found saved snapshot: ${snapshotId}`); console.log('Creating sandbox from snapshot...\n');
// Retrieve the snapshot const snapshot = await Snapshot.get({ snapshotId }); console.log(`Snapshot status: ${snapshot.status}`);
// Create sandbox from snapshot const warmStart = Date.now(); const sandbox = await Sandbox.create({ source: { type: 'snapshot', snapshotId: snapshot.snapshotId }, timeout: ms('10m'), }); const warmTime = Date.now() - warmStart;
console.log(`Sandbox created: ${sandbox.sandboxId}`); console.log(`Warm start time: ${(warmTime / 1000).toFixed(2)}s`);
// Verify dependencies are already installed console.log('\nVerifying pre-installed dependencies...'); const check = await sandbox.runCommand({ cmd: 'ls', args: ['node_modules'], }); const modules = await check.stdout(); const count = modules.split('\n').filter(Boolean).length; console.log(`Found ${count} packages in node_modules`);
// Show timing comparison if (coldStartTime) { const saved = ((coldStartTime - warmTime) / 1000).toFixed(1); console.log(`\n--- Timing Comparison ---`); console.log(`Cold start (install deps): ${(coldStartTime / 1000).toFixed(2)}s`); console.log(`Warm start (from snapshot): ${(warmTime / 1000).toFixed(2)}s`); console.log(`Time saved: ${saved}s`); }
// Clean up await sandbox.stop(); console.log('\nSandbox stopped'); console.log('(Snapshot is still saved - run again to reuse it)'); console.log('(Delete snapshot-id.txt to start fresh)'); } else { await createAndSnapshot(); }}
async function createAndSnapshot() { const totalStart = Date.now();
console.log('Creating new sandbox...'); const sandbox = await Sandbox.create({ resources: { vcpus: 2 }, timeout: ms('10m'), runtime: 'node22', }); console.log(`Sandbox created: ${sandbox.sandboxId}`);
// Install some dependencies to simulate real setup console.log('\nInstalling dependencies...'); const install = await sandbox.runCommand({ cmd: 'npm', args: ['install', 'typescript', 'eslint', 'prettier', 'zod', '@anthropic-ai/sdk'], stdout: process.stdout, stderr: process.stderr, });
if (install.exitCode !== 0) { console.log('Installation failed'); await sandbox.stop(); process.exit(1); }
const totalTime = Date.now() - totalStart; console.log(`\nSetup completed in ${(totalTime / 1000).toFixed(2)}s`);
// Take snapshot console.log('\nTaking snapshot...'); const snapshot = await sandbox.snapshot(); // Note: sandbox is now stopped automatically
console.log(`Snapshot created: ${snapshot.snapshotId}`); console.log(`Snapshot status: ${snapshot.status}`);
// Save for later writeFileSync(SNAPSHOT_FILE, snapshot.snapshotId); writeFileSync(TIMING_FILE, totalTime.toString());
console.log(`\nSaved snapshot ID to ${SNAPSHOT_FILE}`); console.log('Run this script again to restore from snapshot!');}
main().catch(console.error);Run the script with environment variables loaded:
npx dotenv-cli -e .env.local -- npx tsx index.tsFirst run output (creates snapshot):
Creating new sandbox...Sandbox created: sbx_abc123
Installing dependencies...added 45 packages in 8s
Setup completed in 10.24s
Taking snapshot...Snapshot created: snap_xyz789Snapshot status: ready
Saved snapshot ID to ./snapshot-id.txtRun this script again to restore from snapshot!Second run output (restores from snapshot):
Found saved snapshot: snap_xyz789Creating sandbox from snapshot...
Snapshot status: readySandbox created: sbx_def456Warm start time: 2.31s
Verifying pre-installed dependencies...Found 45 packages in node_modules
--- Timing Comparison ---Cold start (install deps): 10.24sWarm start (from snapshot): 2.31sTime saved: 7.9s
Sandbox stopped(Snapshot is still saved - run again to reuse it)(Delete snapshot-id.txt to start fresh)Call snapshot() on a running sandbox to save its state:
const snapshot = await sandbox.snapshot();console.log(snapshot.snapshotId); // snap_abc123Important: The sandbox stops automatically after snapshotting. You cannot run more commands on it.
Pass the snapshot ID as the source when creating a new sandbox:
const sandbox = await Sandbox.create({ source: { type: 'snapshot', snapshotId: snapshot.snapshotId }, timeout: ms('10m'),});- Snapshots expire after 7 days
- You can create multiple sandboxes from the same snapshot
- Deleting a snapshot does not affect sandboxes already created from it
For more details, see the Snapshotting documentation.
| Scenario | Use |
|---|---|
| Keep sandbox warm between commands | Sandbox.get() |
| Reuse setup across sessions/days | Snapshot |
| Share environment with teammates | Snapshot |
| Survive sandbox timeout | Snapshot |
| Fastest possible reconnect | Sandbox.get() |
- Learn about Sandbox.get() for reconnecting to running sandboxes
- See the Sandbox SDK reference for all available methods