When you create a sandbox, it continues running until it times out or you explicitly stop it. If your script crashes, your connection drops, or you need to interact with the sandbox from a different process, you can reconnect using Sandbox.get().
This is different from snapshots, which save the sandbox state for later restoration. Sandbox.get() connects to a sandbox that is actively running.
You need the Vercel CLI, Node.js 22+, and a Vercel project to link your sandbox and generate an OIDC token.
mkdir sandbox-reconnect-demo && cd sandbox-reconnect-demonpm init -ynpm install @vercel/sandbox msnpm install -D @types/nodevercel linkvercel env pullThis installs the SDK, links to your Vercel project, and creates .env.local with authentication credentials.
Create index.ts with the code below. It demonstrates reconnection by running in two phases:
- Phase 1: Spin up a sandbox, persist its ID to disk, and exit (sandbox keeps running)
- Phase 2: Load the ID, call
Sandbox.get()to reconnect, and compare the timing
import ms from 'ms';import { Sandbox } from '@vercel/sandbox';import { writeFileSync, readFileSync, existsSync, unlinkSync } from 'fs';
const SANDBOX_FILE = './sandbox-id.txt';const TIMING_FILE = './cold-start-time.txt';
async function main() { if (existsSync(SANDBOX_FILE)) { // Reconnect to existing sandbox const sandboxId = readFileSync(SANDBOX_FILE, 'utf-8').trim(); const coldStartTime = existsSync(TIMING_FILE) ? parseInt(readFileSync(TIMING_FILE, 'utf-8').trim()) : null;
console.log(`Found existing sandbox: ${sandboxId}`); console.log('Reconnecting...\n');
try { const reconnectStart = Date.now(); const sandbox = await Sandbox.get({ sandboxId }); const reconnectTime = Date.now() - reconnectStart;
console.log(`Reconnected to: ${sandbox.sandboxId}`); console.log(`Reconnect time: ${(reconnectTime / 1000).toFixed(2)}s`);
// Show timing comparison if (coldStartTime) { console.log(`\n--- Timing Comparison ---`); console.log(`Cold start: ${(coldStartTime / 1000).toFixed(2)}s`); console.log(`Warm reconnect: ${(reconnectTime / 1000).toFixed(2)}s`); console.log(`Speedup: ${(coldStartTime / reconnectTime).toFixed(1)}x faster`); }
// Clean up await sandbox.stop(); unlinkSync(SANDBOX_FILE); if (existsSync(TIMING_FILE)) unlinkSync(TIMING_FILE); console.log('\nSandbox stopped and cleaned up'); } catch (error) { console.log('Could not reconnect, creating new sandbox...'); unlinkSync(SANDBOX_FILE); if (existsSync(TIMING_FILE)) unlinkSync(TIMING_FILE); await createNewSandbox(); } } else { await createNewSandbox(); }}
async function createNewSandbox() { const startTime = Date.now(); console.log('Creating new sandbox...');
const sandbox = await Sandbox.create({ timeout: ms('10m'), runtime: 'node22', });
const totalTime = Date.now() - startTime;
// Save the ID and timing for later writeFileSync(SANDBOX_FILE, sandbox.sandboxId); writeFileSync(TIMING_FILE, totalTime.toString());
console.log(`Sandbox created: ${sandbox.sandboxId}`); console.log(`Cold start time: ${(totalTime / 1000).toFixed(2)}s`); console.log('\nRun this script again to see reconnect speed!');}
main().catch(console.error);Execute the script twice in quick succession:
npx dotenv-cli -e .env.local -- npx tsx index.tsFirst execution:
Creating new sandbox...Sandbox created: sbx_abc123Cold start time: 2.34s
Run this script again to see reconnect speed!Second execution (before the 10-minute timeout):
Found existing sandbox: sbx_abc123Reconnecting...
Reconnected to: sbx_abc123Reconnect time: 0.31s
--- Timing Comparison ---Cold start: 2.34sWarm reconnect: 0.31sSpeedup: 7.5x faster
Sandbox stopped and cleaned up- Script recovery: Reconnect after a crash without losing your running environment
- Multi-process workflows: Access the same sandbox from different scripts or terminals
- CLI tools: Separate sandbox lifecycle management from command execution
- Interactive development: Keep a sandbox warm between debugging sessions
If the sandbox timed out or was stopped, Sandbox.get() throws an error. Always wrap it in a try-catch:
try { const sandbox = await Sandbox.get({ sandboxId }); console.log('Reconnected successfully');} catch (error) { console.log('Sandbox no longer available, creating a new one...'); const sandbox = await Sandbox.create({ runtime: 'node22' });}| Operation | Typical Time |
|---|---|
| Create new sandbox | ~2-3s |
Reconnect with Sandbox.get() | ~0.3s |
The ~10x speedup makes Sandbox.get() ideal for keeping sandboxes warm between commands.
| Sandbox.get() | Snapshot.get() | |
|---|---|---|
| Target | Running sandbox | Saved state |
| Requirement | Sandbox must be active | Sandbox can be stopped |
| Persistence | Until timeout | 7 days |
| Best for | Interactive sessions | Reusable templates |
- Learn about snapshots for persisting sandbox state across sessions
- See the Sandbox SDK reference for all available methods