Define the APIs expected from the system. This is your chance to analyze and define the read and write paths so that you can come up with the high-level design...
// send out a notification
POST notification-service/v1/notification
Req JSON: {
notificationData:
deliveryTime:
asap: true | false
fanOutNumber (optional): number
type: MARKETING | TRANSACTIONAL | ...
users (optional):
} -> notificationId
/**
asap would mean deliver as soon as possible
if asap == false and deliveryTime in future -> schedule
users field would be populated when the notification is meant for a certain set of users - example for OTP notifications
Sender info can be derived from the JWT - not passed in the request
**/
POST notification-service/c1/batchNotification
Req JSON: {
{
notificationData:
deliveryTime:
asap: true | false
fanOutNumber (optional): number
type: MARKETING | TRANSACTIONAL | ...
users (optional):
}[]
} -> notificationId[]
// user engagement
POST notification-service/v1/engagement
Req JSON: {
notification:
action: CLICK | DISMISS | OPEN | ...
} -> success / failure
// user attributes for targetting
PATCH notification-service/v1/attributes
Req JSON: {
attributes:
opt-in: MARKETING | TRANSACTIONAL | ...
opt-out: MARKETING | TRANSACTIONAL | ...
} -> success/failure
userId would not be passed in the POST API body, but would be taken in from the JWT in the headers -> increased security.
Describe the overall system architecture. Identify the main components needed to solve the problem end-to-end. Use the diagramming tool to create a block diagram.
Delivering Notifications -
Batched notifications are expanded in the targeting service and treated as normal notifications post this.
User preferences and attributes -
The user preferences/attributes API arrives at the LB and is sent to the user DB from where these preferences would be used to decide targets from the next notification onwards.
User engagement -
User engagement metrics would arrive at the APIGW and would be saved in the engagement DB
Define the data model. Identify the main entities, their attributes, and relationships. Consider the choice of database type (SQL vs NoSQL) and justify your decision based on access patterns...
User DB -
Notifications DB -
Engagement DB -
Deep dive into 2-3 key components. Explain how they work, how they scale, discuss tradeoffs, capacity, and any relevant algorithms or data structures.
Targeting service:
The targeting service gets the notifications and batch notifications and is responsible for assigning the users to which the notification would be sent. To do that targeting service runs a rule engine on top of the attribute it receives from the notification as well as the users preferences stored in the users DB. In case of increase demand or increased load the targetting service can be horizontally scaled up so that multiple instances of the service run. But all the instances can be a part of the same consumer group so that and no message is duplicated or a single message is not sent to more than one instances of the target in service to a sign targets to it. This increases the overall availability of the system as well as it keeps the doors open for future optimizations.
Scheduler service:
The scheduler service receives the messages from the message queue in which the targeting service sends the messages. The scheduler service will have the notifications as well as the intended recipients of those notifications. based on when that notification needs to be sent - do we need to send the notification as soon as possible or do we need to schedule that notification for leter, the scheduler service with either just store that notification to the notification DB or store in DB and pass that along to the find out service.
Fanout service:
The fan out service has integrations with apns FCM email and SMS delivery networks to forward the notification to the end user or the clients which either use IOS or use Android or use email or SMS. The fan out service will be responsible for getting a success of failure response from the final vendor and based on whether the request has succeeded or failed the fan out service will try to resend or redelivere the notification up to a certain number of times like 3. In case of persistent failure, the messages would be sent to a dead letter queue. The fanout service will also update the delivery status of a notification in the notifications DB.
Scalability:
All are components can be horizontally skilled to ensure that our service is scalable. We would also use auto configuration checks to check which components have gone down and to auto scale them up in case in case the traffic Spikes or the components shutdown. Here we would need to take care of partitioning in the message queues to ensure a) in order delivery and b) message queues can also be scaled up.
Latency:
Latency in our case for message delivery or notification delivery will depend on three things the first is how quickly are we able to use the targeting service to find the intended targets; second how quickly are we able to scale up our individual components in response to increase traffic; the third how responsive or end vendors like apns fcm or the email service providers are.
For the targetting service - We are making a user DB call for each notification that we get. To reduce latency for the targeting we can include another data source which lies between the user DB and the targeting service and which relays for a given message attributes which users would be the best fit for being the intended recipients. This data source needs to be synced on a periodic basis with the userDB and the engagement DB to be responsive to changes in preferences. This new data source can be keyed with the notification attributes for fast target lookup.