15 questions found
How would you implement idempotent notification sending to avoid sending a duplicate email if a background job is retried?
Advanced
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?
Background Jobs & Queues;Databases & ORMs (MongoDB/Mongoose
SQL/Sequelize)
What is the difference between sending SMS via a provider's REST API (like Twilio) versus using SMTP-based email in terms of a Node.js integration?
Intermediate
SMS providers like Twilio expose a REST API (rather than a legacy protocol like SMTP), meaning integration is via straightforward HTTP requests with the provider's SDK handling authentication and request formatting -- unlike email's store-and-forward SMTP model with variable, unpredictable delivery timing across different mail servers, SMS delivery is typically much faster and the provider's API often gives more immediate delivery-status feedback via webhooks.
const twilio = require('twilio')(accountSid, authToken);
await twilio.messages.create({
body: 'Your verification code is 123456',
from: '+15017122661',
to: user.phoneNumber,
});
Real-world example
A two-factor authentication feature sends a six-digit verification code via Twilio's SMS API, relying on Twilio's typically sub-second delivery time and near-immediate delivery-status webhook, both faster and more predictable than an equivalent email-based verification flow would be.
Common follow-ups: How do you handle international phone number formatting and validation before attempting to send an SMS?;What's the cost consideration of SMS versus email at scale, given SMS is typically billed per message?
HTTP & HTTPS Modules;Authentication & Authorization (JWT
OAuth
Passport)
How would you design a notification preference center allowing users to control which types of notifications they receive via which channels?
Advanced
A preference center models notification types (order updates, marketing, security alerts) and channels (email, SMS, push) as a matrix, with per-user preferences stored typically as a set of boolean flags or an object per notification-type/channel combination -- critically, some notification types (like security alerts about a password change) are often deliberately non-optional regardless of user preference, since allowing users to fully disable security-critical communications introduces its own risk.
// User preference document
{
userId: '123',
preferences: {
orderUpdates: { email: true, sms: false, push: true },
marketing: { email: false, sms: false, push: false },
securityAlerts: { email: true, sms: true, push: true }, // not user-configurable
}
}
Real-world example
An e-commerce platform lets users disable marketing emails entirely and choose SMS versus push for order updates, while security-related notifications like 'new device login detected' remain mandatory across at least the email channel regardless of the user's other preferences.
Common follow-ups: How would you migrate existing users to a new preference schema when adding a new notification type or channel?;Should a user be able to fully opt out of a specific notification type, or should some minimum channel always remain mandatory?
Security;Databases & ORMs (MongoDB/Mongoose
SQL/Sequelize)
What is the difference between the 'to', 'cc', and 'bcc' fields when sending an email programmatically, and why does 'bcc' matter for privacy?
Beginner
'to' and 'cc' (carbon copy) recipients are visible to every other recipient of the email, while 'bcc' (blind carbon copy) recipients receive the email without their address being visible to anyone else on the message -- this matters significantly when sending the same email to a list of unrelated users, where using 'to' or 'cc' for the whole list would expose every recipient's email address to every other recipient, a privacy mistake often made by accident.
// Privacy risk: every recipient sees everyone else's email address
await transporter.sendMail({ to: allUserEmails.join(','), subject: 'Update' });
// Better for a shared announcement to unrelated users
await transporter.sendMail({ to: 'noreply@example.com', bcc: allUserEmails.join(','), subject: 'Update' });
Real-world example
A company accidentally exposed the email addresses of hundreds of newsletter subscribers by putting them all in the 'to' field of a single email instead of 'bcc', a mistake corrected in their process by always using bcc for bulk sends to unrelated recipients going forward.
Common follow-ups: In what legitimate scenario would you actually want to use 'cc' rather than 'bcc' or 'to' alone?;How do bulk email providers like SendGrid handle sending personalized emails to many recipients without this to/bcc pitfall at all?
Security;HTTP & HTTPS Modules
How would you test that a Node.js application correctly sends emails without actually sending real emails during automated tests?
Intermediate
Rather than hitting a real email provider during tests (slow, costly, and dependent on external network availability), tests typically mock the email-sending function or transport entirely, asserting that it was called with the expected arguments (recipient, subject, relevant content) -- some teams additionally use a tool like Ethereal Email or Mailhog, a fake SMTP server for local/CI testing that captures sent emails for inspection without any real delivery.
jest.mock('../emailService');
test('sends a welcome email on registration', async () => {
await registerUser({ email: 'test@example.com' });
expect(emailService.sendWelcomeEmail).toHaveBeenCalledWith(
expect.objectContaining({ email: 'test@example.com' })
);
});
Real-world example
A test suite for a registration flow mocks the email service entirely, verifying only that sendWelcomeEmail was called with the correct user data, avoiding any dependency on network access or a real (or even fake) SMTP server during fast, reliable unit tests.
Common follow-ups: What's the tradeoff between mocking the email function versus using a fake SMTP server like Mailhog for integration-level testing?;How would you write an end-to-end test that verifies an actual email's content and formatting render correctly?
Testing with Jest
Mocha & the Node Test Runner;Background Jobs & Queues