Backend Deep Dive¶
Application lifecycle¶
main.py initializes SQLite, builds AppState, attaches it to app.state.sandbox, starts periodic cleanup, and stops cleanup during lifespan shutdown. The API router depends on this shared state for settings, repositories, runtimes, and exporters.
Route families¶
| Family | Operations |
|---|---|
| Health | /healthz, /readyz, /v1/backends |
| Sessions | create, list, get, heartbeat, stop, delete |
| Execution | create exec, get exec, stdout/stderr offset reads |
| Files | read/write/list/delete, archive upload/download |
| Artifacts | sync and list exports |
| Snapshots | create/list/get/delete |
| Maintenance | /v1/gc |
Session creation¶
The route validates a snapshot’s existence and workspace ownership, chooses microsandbox when restoring, creates a metadata record, creates a scratch workspace, restores an optional archive, starts the runtime, then stores runtime paths and sandbox name. This ordering gives the API a durable record even while runtime setup is in progress.
Concurrency and cleanup¶
Handlers are async, but SQLite repository calls and local filesystem operations are synchronous. Runtime command execution is awaited. Cleanup periodically expires sessions and removes execution logs. A production deployment should consider executor isolation for blocking filesystem/database work and explicit per-session concurrency limits.
Error conventions¶
Missing resources return 404, invalid state transitions return 409, path escapes return 400, and unavailable readiness returns 503. Runtime failures become failed execution records rather than uncaught process crashes.