Skip to main content
Background processes let you run long-running commands that continue executing while your Worker handles other requests. Perfect for web servers, build tools, data processing jobs, and monitoring tasks.

Starting a background process

Use startProcess() to launch commands that run in the background:
const sandbox = getSandbox(env.Sandbox, 'my-sandbox');

// Start a simple HTTP server
const process = await sandbox.startProcess(
  'python3 -m http.server 8000'
);

console.log(`Process started with ID: ${process.id}`);
console.log(`Status: ${process.status}`);

Understanding the Process object

Every process has a rich interface for monitoring and control:
interface Process {
  id: string;              // Unique process identifier
  pid?: number;            // System process ID
  command: string;         // Command being executed
  status: ProcessStatus;   // Current status
  startTime: Date;         // When process started
  endTime?: Date;          // When process ended (if stopped)
  exitCode?: number;       // Exit code (if process terminated)
  sessionId: string;       // Session context

  // Methods
  kill(signal?: string): Promise<void>;
  getStatus(): Promise<ProcessStatus>;
  getLogs(): Promise<{ stdout: string; stderr: string }>;
  waitForLog(pattern: string | RegExp, timeout?: number): Promise<WaitForLogResult>;
  waitForPort(port: number, options?: WaitForPortOptions): Promise<void>;
  waitForExit(timeout?: number): Promise<WaitForExitResult>;
}

Process lifecycle

Processes go through several states:
  • starting - Process is being initialized
  • running - Process is actively executing
  • completed - Process exited successfully (exit code 0)
  • failed - Process exited with non-zero code
  • killed - Process was terminated by signal
  • error - Process failed to start
const process = await sandbox.startProcess('npm run build');

// Check current status
const status = await process.getStatus();
console.log(`Process is ${status}`);

// Wait for completion
const result = await process.waitForExit();
console.log(`Process exited with code ${result.exitCode}`);

Waiting for server readiness

When starting servers, wait for them to be ready before connecting:
// Start a web server
const server = await sandbox.startProcess(
  'python3 -m http.server 8000'
);

// Wait for port to be ready (HTTP check)
await server.waitForPort(8000);

console.log('Server is ready!');

// Now you can expose the port
const exposed = await sandbox.exposePort(8000);
console.log(`Access server at: ${exposed.url}`);

Custom readiness checks

Customize how port readiness is checked:
// Wait for HTTP 200 response
await server.waitForPort(8000, {
  mode: 'http',
  path: '/health',
  status: 200,
  timeout: 30000  // 30 second timeout
});

Streaming process logs

Monitor process output in real-time:
import { parseSSEStream } from '@cloudflare/sandbox';

const process = await sandbox.startProcess('npm run watch');

// Stream logs
const stream = await sandbox.streamProcessLogs(process.id);

for await (const event of parseSSEStream(stream)) {
  switch (event.type) {
    case 'stdout':
      console.log('Output:', event.data);
      break;
    case 'stderr':
      console.error('Error:', event.data);
      break;
    case 'exit':
      console.log('Process exited:', event.exitCode);
      break;
  }
}
Log streaming continues until the process exits or you close the stream. This is perfect for tailing logs or monitoring long-running tasks.

Waiting for log patterns

Wait for specific output before proceeding:
const server = await sandbox.startProcess(
  'node server.js'
);

// Wait for "Server listening" message
const result = await server.waitForLog(/Server listening on port (\d+)/);

console.log('Found:', result.line);
console.log('Port:', result.match?.[1]);

Pattern matching

// Simple string match
await process.waitForLog('Ready to accept connections');

// Regex with capture groups
const result = await process.waitForLog(
  /Database initialized in (\d+)ms/
);
console.log(`Init time: ${result.match?.[1]}ms`);

// With timeout
try {
  await process.waitForLog('Started', 10000);
} catch (error) {
  console.error('Process did not start within 10 seconds');
}

Stopping processes

Terminate processes gracefully or forcefully:
const process = await sandbox.startProcess('long-running-task');

// Send SIGTERM (graceful shutdown)
await process.kill();

// Send SIGKILL (immediate termination)
await process.kill('SIGKILL');

// Or use the sandbox method
await sandbox.killProcess(process.id);

Managing multiple processes

List all processes

const processes = await sandbox.listProcesses();

processes.forEach(proc => {
  console.log(`${proc.id}: ${proc.command} (${proc.status})`);
});

Get process by ID

const process = await sandbox.getProcess('process-id');

if (process) {
  console.log(`Status: ${process.status}`);
  if (process.exitCode !== undefined) {
    console.log(`Exit code: ${process.exitCode}`);
  }
}

Kill all processes

// Kill all running processes
await sandbox.killAllProcesses();

Process options

Customize process behavior with options:
const process = await sandbox.startProcess('node server.js', {
  processId: 'web-server',  // Custom ID for later reference
  cwd: '/workspace/app',    // Working directory
  env: {
    PORT: '8000',
    NODE_ENV: 'production'
  },
  timeout: 300000,          // Kill after 5 minutes
  autoCleanup: false        // Keep process record after exit
});

Common patterns

Development server

// Start dev server with hot reload
const server = await sandbox.startProcess(
  'npm run dev',
  { processId: 'dev-server' }
);

// Wait for it to be ready
await server.waitForLog('Local: http');

// Expose the port
await sandbox.exposePort(5173);

Build pipeline

// Start build process
const build = await sandbox.startProcess('npm run build');

// Monitor progress
const stream = await sandbox.streamProcessLogs(build.id);

for await (const event of parseSSEStream(stream)) {
  if (event.type === 'stdout') {
    // Update build progress UI
    if (event.data.includes('✓')) {
      console.log('Build step completed:', event.data);
    }
  }
}

// Wait for completion
const result = await build.waitForExit();

if (result.exitCode === 0) {
  console.log('Build succeeded!');
} else {
  console.error('Build failed');
}

Database initialization

// Start database
const db = await sandbox.startProcess(
  'postgres -D /workspace/data',
  { processId: 'postgres' }
);

// Wait for ready message
await db.waitForLog('database system is ready to accept connections');

// Run migrations
await sandbox.exec('psql -f /workspace/migrations/init.sql');

console.log('Database ready!');

Log monitoring

// Tail application logs
const tail = await sandbox.startProcess(
  'tail -f /workspace/app.log',
  { processId: 'log-monitor' }
);

// Stream and filter logs
const stream = await sandbox.streamProcessLogs(tail.id);

for await (const event of parseSSEStream(stream)) {
  if (event.type === 'stdout') {
    // Alert on errors
    if (event.data.includes('ERROR')) {
      await sendAlert(event.data);
    }
  }
}

Error handling

Always handle process failures:
try {
  const process = await sandbox.startProcess('npm test');
  
  // Wait for completion with timeout
  const result = await process.waitForExit(60000);
  
  if (result.exitCode !== 0) {
    // Get error logs
    const logs = await process.getLogs();
    console.error('Tests failed:', logs.stderr);
    
    throw new Error(`Tests failed with exit code ${result.exitCode}`);
  }
  
  console.log('All tests passed!');
} catch (error) {
  console.error('Test execution failed:', error.message);
}

Best practices

1
Use custom process IDs
2
Assign meaningful IDs to processes you’ll reference later:
3
await sandbox.startProcess('python3 -m http.server 8000', {
  processId: 'web-server'
});

// Later, easily retrieve it
const server = await sandbox.getProcess('web-server');
4
Set timeouts for finite tasks
5
Previent runaway processes by setting timeouts:
6
await sandbox.startProcess('npm run build', {
  timeout: 300000  // 5 minute max build time
});
7
Monitor critical processes
8
Set up monitoring for important services:
9
const server = await sandbox.startProcess('node server.js');

// Check health periodically
setInterval(async () => {
  const status = await server.getStatus();
  
  if (status !== 'running') {
    console.error('Server died, restarting...');
    await sandbox.startProcess('node server.js');
  }
}, 30000);
10
Clean up processes
11
Kill processes when you’re done to free resources:
12
try {
  const server = await sandbox.startProcess('node server.js');
  // Use server...
} finally {
  await sandbox.killAllProcesses();
}

Next steps

Exposing ports

Make process services accessible via preview URLs

Streaming output

Advanced streaming patterns for real-time updates

Executing commands

Run one-off commands with exec()

Managing files

Work with files and directories

Build docs developers (and LLMs) love