Services
Long-running background processes in a sandbox
Services are long-running background processes managed by the sandbox supervisor. Unlike a command run with exec, a service stays alive across exec calls, survives checkpoint/restore cycles, and can declare dependencies on other services.
Typical uses: databases (Postgres, Redis), HTTP servers, message queues, language runtimes.
Create or update a service
await sandbox.services.upsert('redis', {
cmd: 'redis-server',
args: ['--port', '6379'],
health_port: 6379,
})PUT /v1/services/{name}{
"cmd": "redis-server",
"args": ["--port", "6379"],
"env": { "REDIS_LOGLEVEL": "warning" },
"working_dir": "/data",
"user": "nobody",
"health_port": 6379,
"needs": ["postgres"],
"container": false,
"image": ""
}| Field | Required | Description |
|---|---|---|
cmd | yes | Executable to run |
args | no | Arguments |
env | no | Extra environment variables |
working_dir | no | Working directory |
user | no | Run as this Unix user |
health_port | no | TCP port probed for readiness; service is running when this port accepts connections |
needs | no | Names of services that must reach running status before this one starts |
container | no | Run inside an OCI container |
image | no | OCI image ref; required when container: true |
Start and stop
await sandbox.services.start('redis')
await sandbox.services.stop('redis')POST /v1/services/{name}/start
POST /v1/services/{name}/stopGet status
const svc = await sandbox.services.get('redis')
console.log(svc.status, svc.pid)GET /v1/services/{name}{
"name": "redis",
"cmd": "redis-server",
"status": "running",
"pid": 142,
"container": false
}status is one of "running", "stopped", "failed", or "unknown".
List all services
const services = await sandbox.services.list()
for (const s of services) {
console.log(s.name, s.status)
}GET /v1/servicesDependency ordering
Use needs to declare start-order dependencies. The supervisor waits for each dependency to pass its health check before starting the dependent service.
// postgres must be healthy before pgbouncer starts
await sandbox.services.upsert('postgres', {
cmd: 'postgres',
args: ['-D', '/var/lib/postgresql/data'],
health_port: 5432,
})
await sandbox.services.upsert('pgbouncer', {
cmd: 'pgbouncer',
args: ['/etc/pgbouncer/pgbouncer.ini'],
needs: ['postgres'],
health_port: 6432,
})
await sandbox.services.start('pgbouncer') // starts postgres first automaticallyContainer services
Set container: true to run the service inside an OCI container. Provide the image reference in image.
await sandbox.services.upsert('app', {
cmd: 'node',
args: ['server.js'],
container: true,
image: 'node:20-slim',
env: { PORT: '3000' },
health_port: 3000,
})
await sandbox.services.start('app')Exec inside a container service
For container: true services, run a one-shot command inside the container:
const result = await sandbox.services.exec('redis', ['redis-cli', 'ping'])
console.log(result.stdout) // "PONG\n"POST /v1/services/{name}/exec{ "cmd": ["redis-cli", "ping"], "timeout_secs": 10 }Note: this endpoint uses timeout_secs, not timeout_ms like /v1/exec.
Services and checkpoint restore
When you restore a checkpoint, the supervisor automatically restarts services that were running at checkpoint time. The restore response includes started_services, stopped_services, and failed_services so you can verify the expected set came back up. See Checkpoint Restore.
Delete a service
await sandbox.services.delete('redis')DELETE /v1/services/{name}Stops and removes the service definition.