[iris]
Concepts

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": ""
}
FieldRequiredDescription
cmdyesExecutable to run
argsnoArguments
envnoExtra environment variables
working_dirnoWorking directory
usernoRun as this Unix user
health_portnoTCP port probed for readiness; service is running when this port accepts connections
needsnoNames of services that must reach running status before this one starts
containernoRun inside an OCI container
imagenoOCI 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}/stop

Get 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/services

Dependency 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 automatically

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

On this page