How to use snapshots for faster sandbox startup

Learn how to save sandbox state with snapshots and skip installation on future runs.

4 min read
Last updated January 29, 2026

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:

  1. Set up your environment once (install deps, configure tools)
  2. Take a snapshot to save that state
  3. 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-demo
cd sandbox-snapshot-demo
npm init -y
npm install @vercel/sandbox ms
npm install -D @types/node

Link your project to Vercel and pull the OIDC token for local development:

vercel link
vercel env pull

The 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.ts

First 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_xyz789
Snapshot status: ready
Saved snapshot ID to ./snapshot-id.txt
Run this script again to restore from snapshot!

Second run output (restores from snapshot):

Found saved snapshot: snap_xyz789
Creating sandbox from snapshot...
Snapshot status: ready
Sandbox created: sbx_def456
Warm start time: 2.31s
Verifying pre-installed dependencies...
Found 45 packages in node_modules
--- Timing Comparison ---
Cold start (install deps): 10.24s
Warm start (from snapshot): 2.31s
Time 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_abc123

Important: 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.

ScenarioUse
Keep sandbox warm between commandsSandbox.get()
Reuse setup across sessions/daysSnapshot
Share environment with teammatesSnapshot
Survive sandbox timeoutSnapshot
Fastest possible reconnectSandbox.get()

Was this helpful?

supported.
How to use snapshots for faster sandbox startup | Vercel Knowledge Base