Architecture · 11.08
The Job Queue
The background job-processing layer behind long-running, non-request-scoped work.
Replacing a queue that lost work on restart
An earlier job queue implementation dispatched via queueMicrotask — fast, but every queued job vanished on a server restart, with no worker-pool model behind it at all. That's a real problem for genuinely long-running, multi-day work like a large codebase migration or continuous monitoring, which can easily outlive several deploys. The current queue is polling-based and durable, backed by SQLite's own async_jobs table: enqueuing inserts a pending row and returns immediately, and a background poller periodically claims rows whose scheduled time has passed, marks them running, and dispatches them for real.
Failure handling that assumes crashes will happen
A failed job retries with exponential backoff up to a maximum attempt count before finally being marked failed — not retried forever. A job stuck in running because the process that claimed it crashed mid-execution is reclaimed automatically once its lease expires, the same lease-and-reclaim pattern the Durable Entity spine and the channel turn queue both use — one recurring idiom for "how do we recover from a crash mid-job," reused rather than reinvented per subsystem. The backend is kept behind a stable interface specifically so a future move to something like BullMQ plus Redis, if the platform ever needs that scale, would be a drop-in replacement rather than a rewrite.
Continue
Why an unchanged workflow graph resumes without re-validation, and how assets get deduplicated by SHA-256.
build_workflow, workflow.validate/dry_run/test/harden/bless, run.await/status/diagnose/replay, trace.inspect, and evaluate.