Skip to content
Docs

How to reconnect to a running Sandbox

Learn how to use Sandbox.get() to reconnect to an existing sandbox from a different process or after a script restart.

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.

Copy link to headingPrerequisites

You need the Vercel CLI, Node.js 22+, and a Vercel project to link your sandbox and generate an OIDC token.

Copy link to heading1. Set up the project

mkdir sandbox-reconnect-demo && cd sandbox-reconnect-demo
pnpm init
pnpm add @vercel/sandbox dotenv
pnpm add -D @types/node
vercel link
vercel env pull

This installs the SDK, links to your Vercel project, and creates .env.local with authentication credentials.

Copy link to heading2. Write the script

Create index.ts with the code below. It runs in two phases:

  • Phase 1: Create a sandbox, persist its ID to disk, and exit
  • Phase 2: Load the ID, call Sandbox.get() to reconnect
import { config } from 'dotenv';
config({ path: '.env.local' });
import { Sandbox } from '@vercel/sandbox';
import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'fs';
const ID_FILE = './sandbox-id.txt';
async function main() {
if (existsSync(ID_FILE)) {
const id = readFileSync(ID_FILE, 'utf-8').trim();
try {
const sandbox = await Sandbox.get({ sandboxId: id });
console.log(`Reconnected to ${sandbox.sandboxId}`);
// Do work here...
await sandbox.stop();
unlinkSync(ID_FILE);
} catch {
unlinkSync(ID_FILE);
await createSandbox();
}
} else {
await createSandbox();
}
}
async function createSandbox() {
const sandbox = await Sandbox.create({ timeout: 10 * 60 * 1000 });
writeFileSync(ID_FILE, sandbox.sandboxId);
console.log(`Created ${sandbox.sandboxId}, run again to reconnect`);
}
main().catch(console.error);

Copy link to headingWith timing comparison

To measure the speedup from reconnecting vs cold start:

import { config } from 'dotenv';
config({ path: '.env.local' });
import { Sandbox } from '@vercel/sandbox';
import { readFileSync, writeFileSync, existsSync, unlinkSync } from 'fs';
const ID_FILE = './sandbox-id.txt';
const TIME_FILE = './cold-start.txt';
const read = (f: string) => readFileSync(f, 'utf-8').trim();
const write = (f: string, v: string) => writeFileSync(f, v);
const rm = (f: string) => existsSync(f) && unlinkSync(f);
async function main() {
if (existsSync(ID_FILE)) {
const id = read(ID_FILE);
const coldMs = existsSync(TIME_FILE) ? +read(TIME_FILE) : null;
try {
const start = Date.now();
const sandbox = await Sandbox.get({ sandboxId: id });
const reconnectMs = Date.now() - start;
console.log(`Reconnected in ${(reconnectMs / 1000).toFixed(2)}s`);
if (coldMs) {
console.log(`Cold: ${(coldMs / 1000).toFixed(2)}s → ` +
`${(coldMs / reconnectMs).toFixed(1)}x faster`);
}
await sandbox.stop();
} catch {
console.log('Sandbox expired, creating new...');
}
rm(ID_FILE);
rm(TIME_FILE);
} else {
const start = Date.now();
const sandbox = await Sandbox.create({ timeout: 10 * 60 * 1000 });
write(ID_FILE, sandbox.sandboxId);
write(TIME_FILE, String(Date.now() - start));
console.log(`Created ${sandbox.sandboxId}, run again to reconnect`);
}
}
main().catch(console.error);

Copy link to heading3. Test it out

Execute the script twice in quick succession:

pnpm dlx tsx index.ts

First execution:

Created sbx_abc123, run again to reconnect

Second execution (before the 10-minute timeout):

Reconnected in 0.31s
Cold: 2.34s → 7.5x faster

Copy link to headingUse cases for Sandbox.get()

  • 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

Copy link to headingHandling expired sandboxes

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' });
}

Copy link to headingPerformance

OperationTypical 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.

Copy link to headingKey differences: Sandbox.get() vs Snapshot.get()

Sandbox.get()Snapshot.get()
TargetRunning sandboxSaved state
RequirementSandbox must be activeSandbox can be stopped
PersistenceUntil timeout7 days
Best forInteractive sessionsReusable templates

Copy link to headingNext steps

Related documentation

More Vercel Sandbox guides