Background job queues without a dead-letter path are silent failure sinks: a job that consistently fails disappears from the active queue after its retry cap is exhausted, leaving no record of what went wrong unless you explicitly configure failure handling. For payment-adjacent jobs — subscription renewals, fulfillment triggers, invoice generation — silent failure means lost revenue and customer confusion. Even for non-financial jobs, the absence of a failure path makes debugging a production incident nearly impossible: you know something is wrong because users report it, but the queue gives you no evidence. The observability gap is the core risk, not the job failure itself.
Low because a missing dead-letter path does not cause immediate harm but compounds debugging difficulty and hides systematic failures until user-reported impact escalates.
Add a failed event handler to every Worker and route failures to your alerting stack. In src/lib/worker.ts or wherever workers are initialized:
import * as Sentry from '@sentry/node'
const worker = new Worker('payments', async (job) => {
// ... job processor
})
worker.on('failed', (job, err) => {
console.error(`[queue] Job ${job?.id} (${job?.name}) failed after ${job?.attemptsMade} attempts:`, err)
Sentry.captureException(err, { extra: { jobId: job?.id, jobName: job?.name } })
})
worker.on('error', (err) => {
Sentry.captureException(err)
})
Set removeOnFail: { count: 500 } to keep the last 500 failed jobs in Redis for post-mortem inspection without unbounded storage growth.
ID: ai-slop-cost-bombs.job-hygiene.queue-deadletter-configured
Severity: low
What to look for: When a background job library is in dependencies, walk source files for queue/worker setup calls: new Queue(, new Worker(, inngest.createFunction(, client.publish(. Count all queue setups and verify each has an error-handling configuration: a failed event handler (worker.on('failed', ...)), a removeOnFail option set, a deadLetterQueue config, an inngest onFailure handler, OR a try/catch around the job processor that logs/alerts.
Pass criteria: 100% of queue setups have error-handling configured. Report: "X queue setups inspected, Y with error handling, 0 silent-failure."
Fail criteria: At least 1 queue setup has no error-handling path.
Skip (N/A) when: No background job library in dependencies.
Detail on fail: "1 silent-failure queue: src/lib/worker.ts new Worker('payments', processor) has no .on('failed', ...) listener — failed jobs disappear with no log"
Remediation: Without error handling, failed jobs vanish silently — you only find out when customers complain. Add a failure listener:
// Bad: failures are silent
const worker = new Worker('payments', async (job) => { ... })
// Good: log and alert on failure
worker.on('failed', (job, err) => {
console.error(`Job ${job.id} failed:`, err)
// ... send to Sentry, etc.
})