Design What Happens to Work That Fails for Good
Systems & Architecture · background jobs, errors, status
Updated 2026-08-04
- Accept that some queued work will never succeed, no matter how many times it runs. A malformed row, a deleted destination, or a revoked credential fails identically on every attempt, and after a few tries the system moves it to a dead letter queue.
- Give permanently failed work a visible home. Most products retry silently, give up silently, and leave the user believing the import is still running.
- Separate the three states in the interface, because they need different words and different buttons:
- Still working, with an estimate or a position.
- Failed and will retry automatically, with the next attempt time.
- Failed for good and waiting for a person.
- Say which item failed, not just that the job did. A 4,000 row import that reports one number is unusable, and one that lists the eleven rows that failed is a task someone can finish.
- Offer the action that matches the cause. A permissions failure needs a link to permissions, a malformed file needs the file back, and a temporary outage needs a retry button.
- Let the user retry only what failed. Re-running the whole job to fix eleven rows creates duplicates of the 3,989 that already worked.
- Keep the failed item long enough to be useful and say how long. A quarantine that silently empties after a day is worse than no quarantine.
- Notify when the failure is terminal, not when it is temporary. Interrupting someone for an attempt that will succeed on its own trains them to ignore the notification that matters.
Work that stopped forever is not an edge case, it is a queue that needs a screen.
Related guides