Retries are idempotent — no duplicate sends
Why it matters
A worker that calls the ESP, receives a success response, and then crashes before updating the database leaves the job in an unacknowledged state. BullMQ re-queues it, and the next worker pickup sends an identical transactional email — a password reset, an order confirmation, a payment receipt — to a real recipient who has already received it. CWE-362 covers race conditions on shared resources; this is the classic check-then-act race across a network boundary. Unlike the queue-level dedup check, this pattern fails specifically on the retry after a successful-but-unacknowledged send.
Severity rationale
Critical because worker crashes during ESP network I/O are expected events, not edge cases, and without idempotency guards every crash produces a duplicate transactional email sent to real recipients.
Remediation
Establish the 'sending' status in the database before calling the ESP, and check for it on every retry, in workers/email.worker.ts:
async function processEmailJob(job: Job<EmailJobData>) {
const { campaignId, recipientId } = job.data
const log = await db.emailSendLog.findFirst({
where: { campaignId, recipientId }
})
if (log?.status === 'sent') return
if (!log) {
await db.emailSendLog.create({
data: { campaignId, recipientId, status: 'sending', jobId: job.id }
})
}
const idempotencyKey = `${campaignId}:${recipientId}:${job.id}`
await esp.send({ ...job.data, idempotencyKey })
await db.emailSendLog.update({
where: { campaignId_recipientId: { campaignId, recipientId } },
data: { status: 'sent', sentAt: new Date() }
})
}
DetectionPro
The detection method for this pattern is part of AuditBuffet Pro.
The full method (what to look for, pass and fail conditions, and how results get reported) ships inside the Sending Pipeline & Infrastructure Audit. The pattern definition, severity rationale, and remediation remain openly licensed under CC-BY-4.0.
External references
- cwe · CWE-362 — Concurrent Execution Using Shared Resource With Improper Synchronization
- iso-25010:2011 · reliability.fault-tolerance — Fault Tolerance
Taxons
History
- 2026-04-18·v1.0.0·Initial import from sending-pipeline-infrastructure·automated