Sandbox lifecycle
A sandbox is an isolated execution environment where your code runs. Each sandbox:
- Has a unique identifier (sandbox ID)
- Contains an isolated filesystem
- Runs in a dedicated Linux container
- Persists state between requests
- Exists as a Cloudflare Durable Object
A sandbox is created the first time you reference its ID:
const sandbox = getSandbox(env.Sandbox, 'user-123');await sandbox.exec('echo "Hello"'); // First request creates sandbox
Duration: 100-300ms (cold start) or <10ms (if warm)
The sandbox is running and processing requests. Filesystem, processes, and environment variables persist across requests.
After inactivity, the sandbox may enter idle state. Filesystem state is preserved, but the container may be paused. Next request triggers a warm start.
Sandboxes are explicitly destroyed or automatically cleaned up:
await sandbox.destroy();// All files, processes, and state deleted permanently
Between requests to the same sandbox:
What persists:
- Files in
/workspace
,/tmp
,/home
- Background processes (started with
startProcess()
) - Code interpreter contexts and variables
- Environment variables and port exposures
What doesn't persist:
- Nothing survives
destroy()
- Background processes may stop after container restarts (rare)
const sandbox = getSandbox(env.Sandbox, `user-${userId}`);
User's work persists across sessions. Good for interactive environments, playgrounds, and notebooks.
const sessionId = `session-${Date.now()}-${Math.random()}`;const sandbox = getSandbox(env.Sandbox, sessionId);// Later:await sandbox.destroy();
Fresh environment each time. Good for one-time execution, CI/CD, and isolated tests.
const sandbox = getSandbox(env.Sandbox, `build-${repoName}-${commit}`);
Idempotent operations with clear task-to-sandbox mapping. Good for builds, pipelines, and background jobs.
The first request to a sandbox determines its geographic location. Subsequent requests route to the same location.
For global apps:
- Option 1: Multiple sandboxes per user with region suffix (
user-123-us
,user-123-eu
) - Option 2: Single sandbox per user (simpler, but some users see higher latency)
try { const sandbox = getSandbox(env.Sandbox, sessionId); await sandbox.exec('npm run build');} finally { await sandbox.destroy(); // Clean up temporary sandboxes}
Destroy when: Session ends, task completes, resources no longer needed
Don't destroy: Personal environments, long-running services
If container crashes or Durable Object is evicted (rare):
try { await sandbox.exec('command');} catch (error) { if (error.message.includes('container') || error.message.includes('connection')) { await sandbox.exec('command'); // Retry - container recreates }}
- Name consistently - Use clear, predictable naming schemes
- Clean up temporary sandboxes - Always destroy when done
- Reuse long-lived sandboxes - One per user is often sufficient
- Batch operations - Combine commands:
npm install && npm test && npm build
- Handle failures - Design for container restarts
- Architecture - How sandboxes fit in the system
- Container runtime - What runs inside sandboxes
- Session management - Advanced state isolation
- Sessions API - Programmatic lifecycle control
Was this helpful?
- Resources
- API
- New to Cloudflare?
- Directory
- Sponsorships
- Open Source
- Support
- Help Center
- System Status
- Compliance
- GDPR
- Company
- cloudflare.com
- Our team
- Careers
- © 2025 Cloudflare, Inc.
- Privacy Policy
- Terms of Use
- Report Security Issues
- Trademark
-