Files
foreman/docs/adr/0008-sqlite-queue.md
2026-05-23 16:41:20 -04:00

1.7 KiB

ADR-0008: Durable SQLite-backed queue

Status: Accepted — 2026-05-23

Context

Jobs are queued, carry state, and may be retried across target sleep/restart. A caller that submitted an async job and is waiting on a webhook must not lose its job because foreman restarted. State must survive process restarts.

Decision

The job queue and all job state (including artifacts, ADR-0006) live in SQLite in WAL mode, via the pure-Go modernc.org/sqlite driver (no CGO, so the Komodo container build stays trivial).

Schema sketch

  • jobs(id TEXT PK, state TEXT, model TEXT, request BLOB, result BLOB, error TEXT, webhook_url TEXT, attempt INT, created_at, updated_at, …)
  • artifacts(job_id TEXT, name TEXT, content_type TEXT, size INT, inline BLOB, PRIMARY KEY(job_id, name))

A single writer (the worker, ADR-0009) plus the HTTP handlers; WAL handles the concurrent-reader / single-writer pattern well at this scale.

Consequences

  • Jobs and results are durable across restarts; webhook recovery via GET /jobs/{id} (ADR-0004) is meaningful.
  • Pure-Go driver keeps cross-compilation and container builds painless.
  • Pruning is a TTL sweep over jobs/artifacts; no external store to operate.
  • SQLite caps practical artifact size at single-digit MB — acceptable per ADR-0006 thresholds; revisit if outputs grow.

Alternatives considered

  • In-memory queue. Loses async jobs on restart; unacceptable given webhooks.
  • Redis / external broker. Another moving part to run for a single-worker daemon; over-engineered. Rejected.
  • mattn/go-sqlite3 (CGO). Faster in some cases but complicates static builds and container images. Pure-Go preferred for ops simplicity.