TSTier SlateAll templates

Infrastructure primitives

Background job queue - at least once, and the retry that doubles it

Why a job queue delivers at least once, and how idempotent workers and dead letters keep retries honest.

  • System design
  • core
  • 8 step walkthrough
  • 5 tables

Share

  • Facebook
  • X

What this board gets wrong on purpose

The tension

The effect ledger is written in the same transaction that completes the job, so a worker that dies after the provider call and before that commit leaves no trace - the lease expires, another worker runs the job, and the only thing standing between the customer and a second charge is the provider honouring our Idempotency-Key. Payment APIs do. Most email and SMS APIs do not, so a crash in that window sends the welcome email twice, and nothing on this board can prevent it. The 60 second lease has the same hole from the other side: a job that runs long without heartbeating is handed to a second worker while the first is still working. And the queue is a table on the application's own Postgres primary - at 1,850 jobs a second it is about 5,500 row writes a second and 160 million dead tuples a day for vacuum, so a backlog after an outage competes for the same disk as the checkout it was meant to take load off.

Practise this as an interview

Take Background job queue - at least once, and the retry that doubles it as a timed system design interview on a blank board - on your own, with the requirements to check yourself against, or with a candidate you invite.

Practise this as an interview

Start here

Why this design

Almost every web application grows a background job queue: send the email after signup, generate the invoice PDF, call the webhook, resize the upload. It is the first place most engineers meet a distributed systems guarantee head on, because a worker can crash between doing the work and saying it did. Interviewers use it to see whether you know what "at least once" means, whether you can make a handler idempotent rather than hoping, and whether you have a plan for the job that fails every single time.

What you will learn

  • Why exactly-once delivery is not on offer, and why at-least-once plus an idempotent handler is the honest substitute.
  • Claiming with FOR UPDATE SKIP LOCKED, leases with a timeout, heartbeats for long jobs, and the reaper that returns abandoned work.
  • Enqueueing in the same transaction as the business write, and the crash window it closes.
  • Exponential backoff with jitter, a maximum attempt count, and why dead letters are a product feature.
  • The one metric that says whether the queue is healthy: the age of the oldest ready job.

How to read this board

  1. Press Play and follow the walkthrough: ENQUEUE on the left, THE QUEUE, the WORKERS, then SIDE EFFECTS on the right.
  2. Then the failure paths: backoff and the reaper under THE QUEUE, DEAD LETTERS along the bottom.
  3. Then OBSERVE on the left - the single number that pages someone.
  4. 1 · Requirements to 6 · Deployment in the written band, then the DATA MODEL.
  5. Then argue with the tension: the duplicate this design cannot prevent, and the primary it shares.

1 · Requirements

Ask these before drawing anything

  • What do the jobs DO? A job that writes only to our own database can be made exactly-once with a transaction. A job that calls the outside world cannot, and the answer for each provider is different.
  • How long does the longest job run? This sets the lease, and a lease shorter than the slowest job is a duplicate generator.
  • Is order required? FIFO per customer is expensive and almost never needed. Ask for the actual business rule.
  • What is the acceptable delay? "Within a second" and "within an hour" are different worker pools and different alerts.
  • What happens to a job that will never succeed? Somebody must look at it. Who, and how quickly?

Functional

  • Enqueue a job with a kind, a JSON payload, an optional run_at, a priority and an idempotency key, inside the caller's transaction.
  • Workers claim ready jobs, run them, and mark them done; at least once delivery.
  • Failed jobs retry with exponential backoff and jitter up to max_attempts, then move to dead letters.
  • Abandoned jobs (worker died) are returned to ready when their lease expires.
  • Dead letters can be inspected and redriven individually or in bulk after a fix.
  • Scheduled and recurring jobs are enqueued by a cron enqueuer with run_at in the future.

Non-functional

  • Pick-up latency: p99 under 2 seconds from ready to running at normal load.
  • Throughput: 2,000 jobs a second sustained, with headroom to drain a one hour backlog in under 30 minutes.
  • No job lost after the enqueueing transaction commits.
  • Duplicates bounded to crashes inside the side-effect window, and every handler documents what a duplicate does.

The rest of this board

Board preview

Available on Tier Slate

This page publishes the question. The answer — 5 more written pages, an 8-step narrated walkthrough and a 5-table schema — is the board itself, and it opens in Tierslate.

  • 5written pages
  • 8walkthrough steps
  • 5tables41 columns

5 pages behind this one

  • Capacity estimation
  • Storage estimation
  • Availability
  • How it works
  • Deployment plan
Open this board in TierslateBrowse every board

More boards

The building blocks an interview asks you to build from scratch.

  • URL shortener - one write, a million reads
  • Distributed cache - the ring, and what a node leaving costs
  • Key-value store - quorums, and where the consistency knob sits
  • Rate limiter - token bucket, and where the counter lives
  • Unique ID generator - 64 bits, and two facts nobody can check
  • Web crawler - a frontier, and the trap of crawling forever
  • Pastebin - a blob store with a short name
  • Load balancer - spreading traffic, and noticing who is dead
  • API gateway - one front door for many services
  • Login and sessions - who you are, on every request
  • Feature flags - a config change that ships like code
  • Secrets manager - the one store everything trusts
  • DNS - the cache that runs the internet
  • Distributed cron - exactly one runner at nine o'clock
  • Code execution sandbox - running a stranger's program
  • Distributed log - Kafka from the partition up
  • Consensus - a leader, a log, and a majority
  • Object storage - eleven nines from cheap disks
All 100 templatesOpen Tierslate
Tierslate

tierslate.com

HomeTemplatesPrivacyTerms