hardSenior Backend EngineerSocial Media
How would you design a real-time notification system that delivers millions of notifications per day?
Posted 18/04/2026
by Mehedy Hasan Ador
Question Details
At a social media company interview:
> "Users need to receive notifications instantly when someone likes their post, comments, or follows them. We have 10M users. How would you design this?"
> "Users need to receive notifications instantly when someone likes their post, comments, or follows them. We have 10M users. How would you design this?"
Suggested Solution
Architecture Overview
Event Producer → Message Queue → Notification Service → Push/Email/In-App
↓
Notification DB
↓
User WebSocket Connection
Component Design
1. Event Ingestion
// Event bus (Kafka/RabbitMQ)
interface NotificationEvent {
type: "LIKE" | "COMMENT" | "FOLLOW" | "MENTION";
fromUserId: string;
toUserId: string;
targetId: string;
timestamp: Date;
}
// Producer: Action happens → publish event
async function onLikePost(likerId: string, postId: string) {
const post = await getPost(postId);
await kafka.produce("notifications", {
type: "LIKE",
fromUserId: likerId,
toUserId: post.authorId,
targetId: postId,
});
}
2. Notification Service (Consumer)
// Process events in batches
kafka.consume("notifications", async (events) => {
// Group by recipient for batch delivery
const grouped = groupBy(events, "toUserId");
for (const [userId, userEvents] of grouped) {
// Check user preferences
const prefs = await getUserPreferences(userId);
const filtered = userEvents.filter(e => prefs.enabledTypes.includes(e.type));
if (filtered.length === 0) continue;
// Store in DB
await db.notification.insertMany(filtered.map(toNotification));
// Deliver via active channel
if (prefs.pushEnabled) await sendPush(userId, filtered);
if (prefs.emailEnabled && meetsThreshold(filtered)) await sendEmail(userId, filtered);
// Real-time via WebSocket
if (wsConnections.has(userId)) {
wsConnections.get(userId).send(JSON.stringify(filtered));
}
}
});
3. WebSocket Delivery
User connects → API Gateway → WebSocket Server (sticky session)
↓
Connection Map: userId → ws connection
4. Scaling Strategy
Key Design Decisions
Aggregation (Don't spam)
// Instead of: "Ahmed liked your post", "Sara liked your post", "John liked your post"
// Send: "Ahmed, Sara, and 5 others liked your post"
Rate Limiting
// Don't send push for every single event
if (notificationsInLastHour(userId) > 10) {
// Batch into digest email instead
scheduleDigest(userId, "hourly");
}