Docs

Architecture · 11.08

The Job Queue

The background job-processing layer behind long-running, non-request-scoped work.

Job queue

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