Run background processes
This guide shows you how to start, monitor, and manage long-running background processes in the sandbox.
Use startProcess() instead of exec() when:
- Running web servers - HTTP servers, APIs, WebSocket servers
- Long-running services - Database servers, caches, message queues
- Development servers - Hot-reloading dev servers, watch modes
- Continuous monitoring - Log watchers, health checkers
- Parallel execution - Multiple services running simultaneously
import { getSandbox } from "@cloudflare/sandbox";
const sandbox = getSandbox(env.Sandbox, "my-sandbox");
// Start a web serverconst server = await sandbox.startProcess("python -m http.server 8000");
console.log("Server started");console.log("Process ID:", server.id);console.log("PID:", server.pid);console.log("Status:", server.status); // 'running'
// Process runs in background - your code continuesimport { getSandbox } from '@cloudflare/sandbox';
const sandbox = getSandbox(env.Sandbox, 'my-sandbox');
// Start a web serverconst server = await sandbox.startProcess('python -m http.server 8000');
console.log('Server started');console.log('Process ID:', server.id);console.log('PID:', server.pid);console.log('Status:', server.status); // 'running'
// Process runs in background - your code continuesSet working directory and environment variables:
const process = await sandbox.startProcess("node server.js", { cwd: "/workspace/api", env: { NODE_ENV: "production", PORT: "8080", API_KEY: env.API_KEY, DATABASE_URL: env.DATABASE_URL, },});
console.log("API server started");const process = await sandbox.startProcess('node server.js', { cwd: '/workspace/api', env: { NODE_ENV: 'production', PORT: '8080', API_KEY: env.API_KEY, DATABASE_URL: env.DATABASE_URL }});
console.log('API server started');List and check running processes:
const processes = await sandbox.listProcesses();
console.log(`Running ${processes.length} processes:`);
for (const proc of processes) { console.log(`${proc.id}: ${proc.command} (${proc.status})`);}
// Check if specific process is runningconst isRunning = processes.some( (p) => p.id === processId && p.status === "running",);const processes = await sandbox.listProcesses();
console.log(`Running ${processes.length} processes:`);
for (const proc of processes) { console.log(`${proc.id}: ${proc.command} (${proc.status})`);}
// Check if specific process is runningconst isRunning = processes.some(p => p.id === processId && p.status === 'running');Wait for a process to be ready before proceeding:
const server = await sandbox.startProcess("node server.js");
// Wait for server to respond on port 3000await server.waitForPort(3000);
console.log("Server is ready");const server = await sandbox.startProcess('node server.js');
// Wait for server to respond on port 3000await server.waitForPort(3000);
console.log('Server is ready');Or wait for specific log patterns:
const server = await sandbox.startProcess("node server.js");
// Wait for log messageconst result = await server.waitForLog("Server listening");console.log("Server is ready:", result.line);const server = await sandbox.startProcess('node server.js');
// Wait for log messageconst result = await server.waitForLog('Server listening');console.log('Server is ready:', result.line);Stream logs in real-time:
import { parseSSEStream } from "@cloudflare/sandbox";
const server = await sandbox.startProcess("node server.js");
// Stream logsconst logStream = await sandbox.streamProcessLogs(server.id);
for await (const log of parseSSEStream(logStream)) { console.log(log.data);}import { parseSSEStream, type LogEvent } from '@cloudflare/sandbox';
const server = await sandbox.startProcess('node server.js');
// Stream logsconst logStream = await sandbox.streamProcessLogs(server.id);
for await (const log of parseSSEStream<LogEvent>(logStream)) { console.log(log.data);}Or get accumulated logs:
const logs = await sandbox.getProcessLogs(server.id);console.log("Logs:", logs);const logs = await sandbox.getProcessLogs(server.id);console.log('Logs:', logs);// Stop specific processawait sandbox.killProcess(server.id);
// Force kill if neededawait sandbox.killProcess(server.id, "SIGKILL");
// Stop all processesawait sandbox.killAllProcesses();// Stop specific processawait sandbox.killProcess(server.id);
// Force kill if neededawait sandbox.killProcess(server.id, 'SIGKILL');
// Stop all processesawait sandbox.killAllProcesses();Start services in sequence, waiting for dependencies:
// Start database firstconst db = await sandbox.startProcess("redis-server");
// Wait for database to be readyawait db.waitForPort(6379, { mode: "tcp" });
// Now start API server (depends on database)const api = await sandbox.startProcess("node api-server.js", { env: { DATABASE_URL: "redis://localhost:6379" },});
// Wait for API to be readyawait api.waitForPort(8080, { path: "/health" });
console.log("All services running");// Start database firstconst db = await sandbox.startProcess('redis-server');
// Wait for database to be readyawait db.waitForPort(6379, { mode: 'tcp' });
// Now start API server (depends on database)const api = await sandbox.startProcess('node api-server.js', { env: { DATABASE_URL: 'redis://localhost:6379' }});
// Wait for API to be readyawait api.waitForPort(8080, { path: '/health' });
console.log('All services running');By default, containers automatically shut down after 10 minutes of inactivity. For long-running processes that may have idle periods (like CI/CD pipelines, batch jobs, or monitoring tasks), use the keepAlive option:
import { getSandbox, parseSSEStream } from "@cloudflare/sandbox";
export { Sandbox } from "@cloudflare/sandbox";
export default { async fetch(request, env) { // Enable keepAlive for long-running processes const sandbox = getSandbox(env.Sandbox, "build-job-123", { keepAlive: true, });
try { // Start a long-running build process const build = await sandbox.startProcess("npm run build:production");
// Monitor progress const logs = await sandbox.streamProcessLogs(build.id);
// Process can run indefinitely without container shutdown for await (const log of parseSSEStream(logs)) { console.log(log.data); if (log.data.includes("Build complete")) { break; } }
return new Response("Build completed"); } finally { // Important: Must explicitly destroy when done await sandbox.destroy(); } },};import { getSandbox, parseSSEStream, type LogEvent } from '@cloudflare/sandbox';
export { Sandbox } from '@cloudflare/sandbox';
export default { async fetch(request: Request, env: Env): Promise<Response> { // Enable keepAlive for long-running processes const sandbox = getSandbox(env.Sandbox, 'build-job-123', { keepAlive: true });
try { // Start a long-running build process const build = await sandbox.startProcess('npm run build:production');
// Monitor progress const logs = await sandbox.streamProcessLogs(build.id);
// Process can run indefinitely without container shutdown for await (const log of parseSSEStream<LogEvent>(logs)) { console.log(log.data); if (log.data.includes('Build complete')) { break; } }
return new Response('Build completed'); } finally { // Important: Must explicitly destroy when done await sandbox.destroy(); } }};- Wait for readiness - Use
waitForPort()orwaitForLog()to detect when services are ready - Clean up - Always stop processes when done
- Handle failures - Monitor logs for errors and restart if needed
- Use try/finally - Ensure cleanup happens even on errors
- Use
keepAlivefor long-running tasks - Prevent container shutdown during processes with idle periods
Check logs to see why:
const process = await sandbox.startProcess("node server.js");await new Promise((resolve) => setTimeout(resolve, 1000));
const processes = await sandbox.listProcesses();if (!processes.find((p) => p.id === process.id)) { const logs = await sandbox.getProcessLogs(process.id); console.error("Process exited:", logs);}const process = await sandbox.startProcess('node server.js');await new Promise(resolve => setTimeout(resolve, 1000));
const processes = await sandbox.listProcesses();if (!processes.find(p => p.id === process.id)) { const logs = await sandbox.getProcessLogs(process.id); console.error('Process exited:', logs);}Kill existing processes before starting:
await sandbox.killAllProcesses();const server = await sandbox.startProcess("node server.js");await sandbox.killAllProcesses();const server = await sandbox.startProcess('node server.js');- Commands API reference - Complete process management API
- Sandbox options configuration - Configure
keepAliveand other options - Lifecycle API - Create and manage sandboxes
- Sessions API reference - Create isolated execution contexts
- Execute commands guide - One-time command execution
- Expose services guide - Make processes accessible
- Streaming output guide - Monitor process output
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
-