LLD: Design Notification System
A notification service where multiple clients publish events, subscribers can subscribe to multiple clients, and each subscriber defines a custom multi-channel notification strategy per client.
1️⃣ Problem Restatement (LLD Framing)
Design a Notification Service that supports:
Multiple Clients (Amazon Shopping, AWS, etc.)
Each client has multiple Subscribers
Notifications have three urgency levels:
HIGH,MEDIUM,LOWEach Subscriber can configure a custom delivery strategy per urgency level per client
Notification channels:
PHONE,SMS,EMAIL(extensible)
System should:
Accept notifications from clients
Resolve subscriber-specific strategies
Deliver notifications via configured channels
2️⃣ Core Design Challenges (What interviewer is testing)
Per-subscriber + per-client + per-severity configuration
Avoid
if-elseexplosionOpen for adding:
New severity
New channel
New client
Clean separation of concerns
Use of Strategy + Composite patterns
3️⃣ Key Entities (LLD Level)
Enums
enum Severity { HIGH, MEDIUM, LOW }
enum ChannelType { EMAIL, SMS, PHONE }
4️⃣ Domain Models
1. Client
class Client {
private final String clientId;
private final String name;
}
2. Subscriber
class Subscriber {
private final String subscriberId;
private final String name;
}
3. Notification
class Notification {
private final String clientId;
private final Severity severity;
private final String message;
}
5️⃣ Strategy Modeling (Most Important Part)
Channel Strategy (Strategy Pattern)
interface NotificationChannel {
void send(Subscriber subscriber, Notification notification);
}
Implementations
class EmailChannel implements NotificationChannel {
public void send(Subscriber subscriber, Notification notification) {
System.out.println("Sending EMAIL to " + subscriber + ": " + notification.message);
}
}
class SmsChannel implements NotificationChannel {
public void send(Subscriber subscriber, Notification notification) {
System.out.println("Sending SMS to " + subscriber);
}
}
class PhoneCallChannel implements NotificationChannel {
public void send(Subscriber subscriber, Notification notification) {
System.out.println("Calling subscriber " + subscriber);
}
}
6️⃣ Per-Severity Delivery Strategy (Composite)
Each severity maps to multiple channels.
class DeliveryStrategy {
private final List<NotificationChannel> channels;
public DeliveryStrategy(List<NotificationChannel> channels) {
this.channels = channels;
}
public void execute(Subscriber subscriber, Notification notification) {
for (NotificationChannel channel : channels) {
channel.send(subscriber, notification);
}
}
}
7️⃣ Subscriber Preferences (Key LLD Object)
👉 This captures per client + per severity configuration
class SubscriptionPreference {
private final String clientId;
private final Subscriber subscriber;
private final Map<Severity, DeliveryStrategy> severityStrategies;
public SubscriptionPreference(
String clientId,
Subscriber subscriber,
Map<Severity, DeliveryStrategy> strategies
) {
this.clientId = clientId;
this.subscriber = subscriber;
this.severityStrategies = strategies;
}
public DeliveryStrategy getStrategy(Severity severity) {
return severityStrategies.get(severity);
}
}
8️⃣ Subscription Registry (In-Memory for LLD)
class SubscriptionRegistry {
// clientId -> list of subscriber preferences
private final Map<String, List<SubscriptionPreference>> registry = new HashMap<>();
public void addSubscription(SubscriptionPreference preference) {
registry
.computeIfAbsent(preference.clientId, k -> new ArrayList<>())
.add(preference);
}
public List<SubscriptionPreference> getSubscribers(String clientId) {
return registry.getOrDefault(clientId, List.of());
}
}
9️⃣ Notification Orchestrator (Main Service)
class NotificationService {
private final SubscriptionRegistry registry;
public NotificationService(SubscriptionRegistry registry) {
this.registry = registry;
}
public void publish(Notification notification) {
List<SubscriptionPreference> subscribers =
registry.getSubscribers(notification.clientId);
for (SubscriptionPreference preference : subscribers) {
DeliveryStrategy strategy =
preference.getStrategy(notification.severity);
if (strategy != null) {
strategy.execute(preference.subscriber, notification);
}
}
}
}
🔟 Example Configuration (From Your Problem Statement)
Subscriber 2 → Amazon Shopping
Map<Severity, DeliveryStrategy> amazonStrategy = Map.of(
Severity.HIGH, new DeliveryStrategy(
List.of(new PhoneCallChannel(), new SmsChannel(), new EmailChannel())
),
Severity.MEDIUM, new DeliveryStrategy(
List.of(new SmsChannel(), new EmailChannel())
),
Severity.LOW, new DeliveryStrategy(
List.of(new EmailChannel())
)
);
Subscriber 2 → AWS
Map<Severity, DeliveryStrategy> awsStrategy = Map.of(
Severity.HIGH, new DeliveryStrategy(
List.of(new PhoneCallChannel(), new EmailChannel())
),
Severity.MEDIUM, new DeliveryStrategy(
List.of(new EmailChannel())
),
Severity.LOW, new DeliveryStrategy(
List.of(new SmsChannel())
)
);
1️⃣1️⃣ Why This Design Works (Interview Gold)
✔ No conditionals on severity or channel
✔ Open/Closed Principle
✔ Easy to add:
New channel → implement
NotificationChannelNew severity → add enum + strategy mapping
New client → config only
✔ Clean separation:Who subscribes →
SubscriptionPreferenceHow to notify →
DeliveryStrategyWhen →
NotificationService
1️⃣2️⃣ Optional Follow-ups Interviewer May Ask
If you want, next we can cover:
Async delivery (Kafka / SQS)
Retry & fallback strategy
Rate limiting per subscriber
Priority queues (H > M > L)
Persisting preferences in DB (schema)
Just tell me 👍
one line for problem statement
Problem Statement (1-liner):
Design a notification service where multiple clients publish events, subscribers can subscribe to multiple clients, and each subscriber defines a custom multi-channel notification strategy per client for each urgency level (High, Medium, Low).


Really solid breakdown of the notification system design. The SubscriptionPreference object is the smartpiece here because it decouples the who-what-how logic so cleanly. I've worked on a similiar system before and we ended up with conditional hell trying to manage per-user preferences - wish we had this strategy pattern approach from day one.