Back to results for “SQL/Sequelize)”
Node.js › Email & Notifications

How would you implement idempotent notification sending to avoid sending a duplicate email if a background job is retried?

Advanced

Answer

Similar to job idempotency discussed earlier, notification sending should track which specific notification (identified by a unique key, like 'order-confirmation-{orderId}') has already been sent, checking that record before sending and skipping (or treating as a no-op) if it's already been dispatched -- this prevents a retried job (due to a worker crash after the email was sent but before the job was marked complete) from sending the same email to a user twice.
async function sendOrderConfirmation(orderId) {
  const alreadySent = await db.sentNotifications.findOne({ key: `order-confirmation-${orderId}` });
  if (alreadySent) return; // idempotent no-op
  await emailProvider.send(buildConfirmationEmail(orderId));
  await db.sentNotifications.insertOne({ key: `order-confirmation-${orderId}`, sentAt: new Date() });
}
Real-world example A customer complaining about receiving three identical order-confirmation emails leads to the discovery that the notification job wasn't idempotent; adding a sent-notification tracking record keyed by order ID prevents any future retries from resulting in duplicate sends.

Common follow-ups: What's the race condition risk if two retries of the same job run concurrently and both check the 'already sent' record before either has recorded their send?;How would you use a database unique constraint to close that specific race condition?