Skip to main content

ADR-0002: Modular monolith + in-process durable worker

Status: Accepted · 2026-07-14

Decision

One deployable server process hosting:
  • the HTTP API (Hono), and
  • a durable worker loop consuming a SQLite-backed work queue with leases, heartbeats, retry classes, and dead-lettering.
Internal module boundaries (folders with explicit public surfaces, no cross-module table access): kernel (db/config/log/audit/authz) · identity · governance · aigateway · connectors · scan (jobs/pipeline) · intelligence (features/inference/clusters/ risk) · review · findings · analyst · actions · search · graph. The worker can also run as a separate process (bun run worker) against the same queue — same code path, no behavior change.

Context

The reference architecture recommends “as few processes initially” while preserving event/module boundaries so connector/extraction workers can scale later. A monolith with a real queue abstraction gives durability semantics (restart-safe scans) without distributed-system overhead the slice cannot validate anyway.

Consequences

  • Queue contract is WorkQueue (enqueue/lease/heartbeat/complete/fail/dead-letter); the SQLite implementation is the dev/test default, an Azure Service Bus implementation is the documented scale path.
  • Pause/resume/cancel operate on job rows at safe stage boundaries, not on threads.
  • Revisit split into separate scanner deployables when a second connector with real throughput exists (trigger: Teams/Exchange live connectors or >1 tenant pilot).