Mermaid source. GitHub renders these natively in Markdown — no image files needed. For the PDF, paste into https://mermaid.live and export PNG.
flowchart TD
web["<b>apps/web</b><br/><span style='font-size:12px'>React 19 · polls every 2s</span>"]
subgraph services["long-running services"]
direction LR
api["<b>apps/api</b><br/><span style='font-size:12px'>Express 5 · :3000</span>"]
worker["<b>apps/worker</b><br/><span style='font-size:12px'>poll 500ms · scales out</span>"]
sched["<b>apps/scheduler</b><br/><span style='font-size:12px'>3 loops · 10s · no leader</span>"]
end
pg[("<b>PostgreSQL 17</b><br/><span style='font-size:12px'>queue + metadata · single source of truth</span>")]
ext["<b>external http</b><br/><span style='font-size:12px'>SSRF-allowlisted</span>"]
web -- "REST + JWT" --> api
api --> pg
worker --> pg
sched --> pg
worker -.-> ext
classDef client fill:#EDEAE3,stroke:#73726C,stroke-width:1.5px,rx:8,color:#2C2C2A
classDef svc fill:#DCE9F7,stroke:#4A6E96,stroke-width:1.5px,rx:8,color:#1B3A5C
classDef store fill:#E4E0F4,stroke:#6B5CA5,stroke-width:1.5px,rx:8,color:#3B2E6E
classDef outside fill:#F7E4DC,stroke:#A5674A,stroke-width:1.5px,rx:8,color:#6E3B2E
class web client
class api,worker,sched svc
class pg store
class ext outside
stateDiagram-v2
[*] --> queued: enqueue (due now)
[*] --> scheduled: enqueue (delayed / cron)
scheduled --> queued: promoter — run_at <= now()<br/>FOR UPDATE SKIP LOCKED
queued --> claimed: claim — FOR UPDATE SKIP LOCKED
claimed --> running: handler starts
running --> completed: success
running --> failed: handler error
running --> queued: SIGTERM drain<br/>(attempt NOT charged)
failed --> scheduled: attempt < max<br/>backoff + full jitter
failed --> dead_letter: attempt >= max
claimed --> queued: lease expired<br/>(attempt refunded)
running --> queued: lease expired<br/>(attempt refunded)
queued --> cancelled: manual
scheduled --> cancelled: manual
dead_letter --> queued: DLQ replay
completed --> [*]
dead_letter --> [*]
cancelled --> [*]
sequenceDiagram
autonumber
participant W1 as worker-1
participant W2 as worker-2
participant PG as PostgreSQL
Note over W1,W2: both poll the same queue at the same instant
W1->>PG: BEGIN — lock queues row FOR UPDATE
W2->>PG: BEGIN — waits on the queue row
W1->>PG: SELECT ... WHERE status='queued'<br/>FOR UPDATE SKIP LOCKED LIMIT n
PG-->>W1: rows 1..n (now locked)
W1->>PG: UPDATE → claimed, lease = now()+30s
W1->>PG: COMMIT
PG-->>W2: queue row released
W2->>PG: SELECT ... FOR UPDATE SKIP LOCKED
Note right of PG: rows 1..n are gone from<br/>the partial index — skipped, not blocked
PG-->>W2: rows n+1..2n
W2->>PG: COMMIT
Note over W1,W2: zero overlap — verified 1000 jobs × 10 workers
sequenceDiagram
autonumber
participant W as worker
participant PG as PostgreSQL
participant R as scheduler (reaper)
W->>PG: claim → lock_expires_at = now()+30s, attempt++
W->>PG: INSERT job_executions (execution_seq = 1)
loop every 5s
W->>PG: heartbeat — extend lease by 30s
end
Note over W: SIGKILL — no clean shutdown
Note over PG: lease stops being extended
loop every 10s
R->>PG: SELECT WHERE lock_expires_at < now()<br/>AND status IN (claimed, running)
end
R->>PG: UPDATE → queued, worker_id = NULL,<br/><b>attempt = attempt - 1</b>
Note right of R: crash is infrastructure failure,<br/>not job failure
W->>PG: (new worker) claim → attempt = 1 again
W->>PG: INSERT job_executions (execution_seq = 2)
Note over PG: seq 1 still 'running' — the audit trail<br/>records the interruption rather than erasing it