In today’s world, notification services are widely employed in almost every product. They’re helpful if you’d like to be alerted of a price change or availability of a product you’re interested in, or if you’d want to be told if a new job specification for a job search criterion you’ve provided becomes available. Getting prompted to take action through our mobile devices’ push notifications, in addition to receiving plain old emails, has become more convenient with the introduction of mobile applications.
In this blog, we’ll be looking at how to design a Notification service. It is an essential component, and almost every product has a notification service used in it hence; as a result, it is one of the most favorite interview topics. So without much delay, let’s dive deep into understanding how to build such type of service!
Before designing we must be sure about the key requirements that we want our notification to deliver. The notification service may be integrated into any existing service and separated from its primary service into its own set of components. Apart from those mentioned above, we must concentrate on the following requirements:
- To be alerted, users should establish a notification to “watch” or “follow” a product.
- If a related event occurs, the service should send users an email or a push notice.
- Even with third-party integration, the notification service should operate.
This will be a critical part of the Notification Service as a whole. We would require APIs that should allow us to create and delete notification entries. To add or delete a notification item, the current service should use an API.
The product search parameters or the selected product can be used as notification criteria. The database saves each criteria entry. The newly created entry will aid the system in determining when the user should be notified. The following APIs would be the most important to us: Our main APIs would be:
-> For creation of new notification event
create_notification( key, product_id, user_id)
-> For deletion of existed notification event
delete_notification( key, notification_id)
-> For getting notification
get_notifications( key, user_id)
A RESTFul or a gRPC service can be used for APIs. For each notification row, we plan to generate and remove. If our solution allows consumers to see the list of alerts that have been produced, we may expect more reads.
Detailed Components Design
We may use a variety of ways to create our notification service. We have the option of using batch jobs or the API internal response logs. However, in this article, we’ll construct our service utilizing the batch jobs technique.
A simple method for alerting would be to run a batch process regularly to see if any user changes are “watched.” Let’s suppose users want to be notified if the price changes; thus, the batch job has to call an internal API that returns the product’s pricing to verify the lowest price.
This method will provide adequate coverage and will cover all of the database’s search criteria. However, as the number of notification items grows, so does the number of calls to the internal API. Scheduler, Data Pipeline, Message Queue, Batch Job, and Communications service is required for the batch jobs-based strategy.
This component may be used to perform our data pipeline, batch processing, and other services regularly, such as daily or weekly.
The following factors influence the start time of the data pipeline and batch processing:
- Off-peak hours: When there is less traffic, we want to check the database for the Notification service.
- User’s time zone: The scheduler should be set to receive the notice when the user is awake. This will undoubtedly result in a higher probability of receiving the notice, especially if it is a push notification.
The data pipeline is told when to start by the scheduler. It searches the database for alerts, organizes them according to criteria, and adds them to a queue. This component reads the Notification API Database. When reading from the Notification API Database, consider the following strategies:
- Full Database scan: The batch job will read all the rows in the Notification API database.
- Partial database scan grouped by regions: The batch job reads the entries based on their region.
The data pipeline will publish the notification items to a message queue after reading them from the database.
Batch jobs are subscribed to the message queue’s notification entries subject. These jobs will pick up the messages from the notification queue. The batch job will use the Internal Pricing or Availability API to retrieve the most up-to-date pricing depending on the database’s notification criteria.
- Compare the most current API pricing to what was previously stored in the database.
- Decide whether or not to alert the user based on the price difference or whether or not the product is available. Sending a request to the Communications component to notify the user.
- We’ll update the notification record in the database when we’ve finished the request to the Communication component. At this time, the last update and Prices fields will need to be changed.
Notification Service Use Case
This part will discuss how notification systems and real-time feeds are implemented using message queues using the Facebook newsfeed notification system.
Assume we’re creating a social network similar to Facebook. To add asynchronous behavior to our program, we’d utilize a message queue. A user will have a large number of followers and friends. One person can have a lot of friends and be friends with a lot of people. We must store a post created by a user in the database. As a result, we’ll need a User table and a Post table. Because a single user can create many posts, the user and posts database will have a one-to-many connection. We must display the user’s post on his friends’ home page while saving the post in the database. This new post necessitates sending a notification to our friends.
Now the question arises, how to send notifications? Let’s find out :)
We can utilize a notification system that is based on push notifications. When data becomes available, the available server will deliver it to the client. As a result, instead of polling the database regularly, we’ll use a message queue to transmit data to the clients.
When a user makes a new post in this method, the system does two distributed activities. One action is to update the database to save the post, which is necessary; otherwise, the data may be lost. Another option is to submit the post’s content to a message queue.
As a result, after the data has been received, the message queue will asynchronously push the post to the user’s connections. As a result, there’s no need to query the database regularly to see if a buddy has made a post. In this approach, we may avoid polling procedures. We can utilize message queue storage with an expiry period to wait for offline users’ connections to come online in the event of offline users. Then send the changes to those individuals.
As a result, combining a push-based technique with message queue implementation may improve application performance while lowering resource consumption.
The database storage procedure must be handled with caution. We can’t push the message to the message queue if it fails since it would generate a system discrepancy. Before sending the message to the message queue, we need to ensure that the database persistence was successful. Otherwise, we’ll have to inform the user that the post could not be created due to server issues.
In this blog, we tried to explain the internal working and design of the notification service. They are used in almost every product, and as a result, it is essential to know about them from the perspective of any system design interview. I hope you liked this blog. Please do share your views.
Enjoy learning, Enjoy algorithms, Enjoy system design!