Yashveer Singh
Connect
<- All posts
Backend, APIs, and System Design11 min read

Async Job Failure Recovery: Patterns That Actually Work

Async jobs fail. Patterns that recover them well share five qualities. Idempotency, exponential backoff with jitter, dead letter queues with alerting, structured retries, and reconciliation jobs. Together they handle the vast majority of failure modes a SaaS will see. The teams that ship them ride out incidents the team that skipped them does not survive.

Written by Yashveer Singh, founder of Yashveer Labs.

What you actually need to know

  • Idempotency is the foundation. Every job must be safe to retry.
  • Exponential backoff with jitter prevents thundering herds.
  • Dead letter queues isolate the problem jobs without blocking the main queue.
  • Reconciliation jobs catch what the live system missed.
  • In my experience, the teams that build these patterns from the start have one tenth the incident volume of teams that retrofit them after the fact.
PatternWhat it solvesEffort
IdempotencyDuplicate side effects on retryModerate, design level
Exponential backoff with jitterThundering herds, transient failuresLow, library level
Dead letter queuePermanent failures blocking progressLow, queue config
Structured retriesDistinguishing transient and permanentLow to moderate
Reconciliation jobSilent failures, driftModerate, per workflow

The core argument

Every SaaS that runs async work eventually hits the failure cases. The network blips. The database deadlocks. The third party API rate limits. The bad input that the validator missed. Each of these is rare. Cumulatively, they happen often enough that a system without recovery patterns generates a steady stream of customer support tickets.

The patterns to handle these failure cases are well known and inexpensive. Idempotency makes retries safe. Exponential backoff with jitter spreads retries over time without overloading the downstream. Dead letter queues isolate the jobs that cannot be recovered automatically. Reconciliation jobs catch what the live system did not catch.

The mistake teams make is treating these as advanced patterns to add later. They are not advanced. They are foundational. A queue without idempotency is a queue that ships duplicate emails, double charges, and inconsistent state at the worst possible moment. A queue without dead letter handling is a queue that grinds to a halt the first time one job repeatedly fails. A system without reconciliation drifts silently until a customer notices.

The right move is to design every async workflow with these patterns from the start. The team that ships them as defaults rarely thinks about queue reliability. The team that skips them spends a lot of time apologizing to customers and explaining incidents.

The five patterns in detail

Pattern one. Idempotency. Every job carries a unique key. The job checks whether the key has been processed before doing the work. Database upserts with unique constraints can serve as the idempotency check. For external API calls, store the idempotency key alongside the request and check it on retry. The pattern is more important than the implementation.

Pattern two. Exponential backoff with jitter. When a job fails on a transient error, wait before retrying. The wait time doubles on each retry. Add random jitter so multiple jobs do not retry at the same moment. The combination prevents thundering herds when the downstream recovers.

Pattern three. Dead letter queue. Jobs that fail all their retries move to a separate queue. The main queue continues processing other jobs. The dead letter queue is monitored. Alerts fire when it accumulates more than a threshold. Engineers triage. Some jobs are resubmitted after a fix. Some are abandoned with a written postmortem.

Pattern four. Structured retries. Not all failures are transient. A bad input fails the same way every time. The retry policy should distinguish. Transient errors retry with backoff. Permanent errors move to the dead letter queue immediately. The error categorization matters more than the retry count.

Pattern five. Reconciliation. A periodic job that scans the system state and corrects inconsistencies. Customer subscriptions that should have been provisioned but were not. Charges that succeeded but did not get recorded. The reconciliation job catches the silent failures that did not bubble up.

What it actually costs

PatternEngineering effortOutcome
IdempotencyOne to two weeks across the job libraryFoundation, enables everything else
Exponential backoff with jitterHours, library levelStandard discipline
Dead letter queue plus alertingOne sprintSurface permanent failures
Structured retries by error classOne sprintFaster recovery, cleaner alerting
Reconciliation jobs per critical workflowOne to two weeks per workflowCatches the silent drift

The full stack costs a few weeks of engineering up front. The payoff is fewer incidents, faster recovery when they happen, and a system that survives the failure cases that test the team's discipline.

Features to demand from your queue system

  • Native support for retries with backoff.
  • A dead letter queue concept built in.
  • Per job idempotency key support.
  • Observability into queue depth, processing time, and failure rate.
  • Alerts on dead letter queue accumulation.
  • A way to replay jobs from the dead letter queue after a fix.

Expert opinion

The teams that ship these patterns from day one have async systems that run quietly. The teams that skip them have async systems that demand constant attention. The work to build the patterns is small. The work to operate without them never ends.

>

Yashveer Singh, founder of Yashveer Labs

How this plays out in practice

On a client project, we shipped the full pattern stack on day one of the queue work. Eighteen months in, the queue has handled tens of millions of jobs. The team has triaged the dead letter queue maybe ten times total. Every triage led to a small fix or a one off resubmission. The team has never had a queue related customer incident.

The opposite story is a project I rescued where the queue had no idempotency. Every transient retry produced duplicate side effects. Customers received duplicate emails. Charges occasionally double posted. The team had spent months patching the symptoms. We added idempotency keys to every job in two sprints and the symptom volume dropped by ninety percent. The lesson was that the patterns are cheap when added early and expensive to retrofit.

For more on the broader topic, see the outbox pattern a SaaS reliability cheat code, the reconciliation job a SaaS pattern founders should know, and background jobs at scale Inngest Trigger Cron and beyond.

Common mistakes teams make

  1. No idempotency. Every retry rolls the dice on duplicate side effects.
  2. Fixed interval retries. The thundering herd makes a small outage worse.
  3. No dead letter queue. The bad job blocks the rest of the queue.
  4. Same retry policy for every error class. Transient and permanent failures handled the same way.
  5. No reconciliation. The silent failures accumulate until a customer notices.
  6. Treating queue reliability as advanced. It is foundational.

Where to start, a 30 day plan

  1. Week one. Audit the existing jobs. List the ones that touch money, identity, or external state. Add idempotency to those first.
  2. Week two. Implement exponential backoff with jitter as a library default. Apply to every job.
  3. Week three. Configure a dead letter queue. Set up alerts on accumulation.
  4. Week four. Build a reconciliation job for the most critical workflow. Schedule it to run daily.

For deeper reading, job failure recovery how good SaaS companies sleep at night covers the operational side, and why your SaaS should have a job queue from day one covers the broader case for async work.

FAQ

Frequently asked

Author

Why you should skip the agency and hire me instead

Agencies markup engineering work by three to five times. Yashveer Singh, founder of Yashveer Labs. I do the work directly. No project manager, no account manager, no overhead. The engineer you talk to is the engineer who writes the code. That changes the math on price, speed, and quality at the same time. If that sounds like the shape of project you have, we should talk.

Related reading