Explore the Architecture Behind a Typical Notification
We are all well aware of the notifications which we receive from the different applications. We get a notification about various activities/services like when we order something from Zomato, MakeMyTrip, or Uber on any such related platform. However, since the process is so engraved in the system, we never bother to know about the functionality of any such system.
As a software developer or technology enthusiast, it will be very fun to understand the system design that is responsible for sending notifications. A notification service is generally a part of the entire product, but very rarely a standalone application unless you are providing it with a SAAS product. We embed the notification service into our application in one way or the other.
The Requirements of a Notification System
So in our notification service, we should be aware of the different functionalities which we want to implement, along with the basic requirement that a notification system should contain. So let's discuss the basic capability of such a system.
Highly Scalable and Available
As for any system, it should be highly scalable and available. Since we can have a notification system built as a SASS or a standalone service, so one thing which we want is that system should be highly available. We can use various concepts for this, like using a queuing mechanism, auto-scaling/on-demand scaling, caching mechanism, etc.
We should always have constraints while sending notifications to the end-users. A customer will normally be interested in thousand of notifications sent to them. As this will always be a hustle for the end-user to clear the clutter of important vs promotional notifications. We need to have some mechanism ready for rate-limiting based on the client.
Moreover, we need to have a track of who is sending the message. We need to have a better understanding of the type of message we are transmitting using our system. This will only help us in accessing the network and other requirements. We can do our scaling based on the stat we will be getting.
Also, it is kind of necessary to have some kind of priority mechanism, since some of the notifications are a higher priority as compared to the others Like some transactional messages, OTP, etc.
The notification system is a kind of mandatory service in almost every product. If you don't have a proper notification system then there are higher chances you might lose some of the best user experiences that can be given to the customers. This article is mainly in context for the software developer who would be willing to develop such a system and also can be a brief understanding for your next system design interview.
So we have a basic architecture already ready with us. As for building any complex product, we need to have the basics clear because even Rome was not built in a day, so how can we expect the same with our product. There can be many use cases which are specific to a product or service that a developer explores along with the process. let us start with our design for our notification service saas model. Possible system design for the notification system. Since we have a saas notification system of course we will be having various clients. Let us discuss all the services in chronological order.
Front-end handler service.
The frontend handler service will be the one that would be responsible for doing various activities like registering the clients and storing the user data like subscribed channels, device IDs, and other basic meta-information. Also, it will add all the messages to the queue so that we have a system that can support a huge lot of notifications.
User management Service and Notification Preference service
We will be having separate services for user management and notification reference and rate limiter, to which our frontend handler service will be communicated. The user management service will be handling the user-related data. This service will also use Redis for faster read access since it would be read-intensive data. On the other hand, there would be a notification preference service which will be maintaining information like the time preference, priority and rate limiter that we will be using while sending the notification. We don't want to irate the customer by sending them thousands of notifications.
Queuing mechanism (Rabbit MQ).
We need to have some sort of queueing mechanism in a system since we would be having various clients who would be dispatching the notification time and again. Notification is something which will have different priorities and we can't afford to lose them.
The various mission-critical application that relies upon the notification system will get affected if the proper notification is not getting delivered. This will help our product in handling a large number of requests, as we don't have to handle all the requests at once. The request can wait.
Although we don't have a load balancer drawn in the diagram, I want to draw your attention to the functionality of a load balancer that would be used in front of any server. Loadbalancer provides you with an application to scale gracefully. The reverse proxy will help solve various purposes like load balancing the request to different servers, adding proper status codes, adding headers to our request, etc. It will help us in eliminating the downtime i.e. in the case any of the servers was down we have other servers that will take care.
Sample Load Balancer Design I don't want to explicitly add load balancers everywhere, as we understood the use of a load balancer. We can add them where ever we feel it is required. Also, there is a concept of autoscaling which help scale our application while the load increases. We can configure this in respect of the percentage of traffic, server utilisation and various other factors.
Notification Management Service
Notification management service is sort of the heart of our entire application. Our notification management service will communicate with Rabbitmq i.e. our queuing service, user management service, notification preference and rate limit and service. It will receive the notification by subscribing to a particular RabbitMq channel. The notification service after receiving the message will connect with the user management service to collect the user-related data like name, deviceIds and other metadata that the user has provided. Apart from getting user-related data and notification management services should also be aware of the notification preference that the user has opted for. For example, a user might have asked for a notification on their email between 10 AM to 10 PM. We have the data of user-related services amalgamated with notification management services. We are good to go with the final pushing of our parsed data into another queue. So the reason for pushing the data into another queue is to create multiple channels for different devices like email, phone notification SMS, etc.
Notification Metadata Information Service
I want a notification metadata information service that is nothing but can be considered like a tracker which will be storing the mission-critical information. This service will help us in tracking, maintaining and drawing different kinds of graphs and other stats that can be utilised will be required for upscaling our system. By having the stats that a particular service takes more load compared to the other services we will be able to achieve functionality. Also collecting the metadata will help us design our system better knowing the critical information like the type of notifications that are commonly consumed.
The Final Queue
The queue is the most used for storing the finally parsed data based upon the type of notification which we are planning to send to the end-user. We could have directly triggered the message from the notification management service. The issue with that approach could be losing critical notifications. The chances are many times the devices might not be connected to the internet. This will easily lead to losing the message that needs to be transferred. The notification is always critical we can’t afford to lose them. Adding the final queue will make our product resilient, as we won't be losing any data. A queue will be supporting the acknowledgement signals which will make sure that the device is fully connected and has received the notification. Once we get the acknowledgement signal then only it will remove the notification data from the queue otherwise it will keep it waiting.
So we have now defined a basic structure for our notification system. Although by no means this is an exhaustive list. We have thousands of use cases which any application faces. We can have various other services integrated like a proper caching mechanism and a database which will help users store the data for other analysis and much more. A very popular use case that slack has recently shared through the flow diagram was when a user is logged in to various devices. But many times the user only wants the receive the notification on a single device at a time. So such use cases we need to handle. This is a constant up-gradation of the product, and it will always keep on happening. So keep exploring and adding new capabilities to your service. Morever, there is this quote which I learned recently like to share. Hope you will like it.
Quote of the day.
A person might complete their time in this world one day, but the knowledge which we share will remain forever. We should always consider sharing the things that we learn. Somewhere someone might get something good out of it.
About The Author Apoorv Tomar is a software developer and part of Mindroast. You can connect with him on Twitter, Linkedin, Telegram and Instagram. Subscribe to the newsletter for the latest curated content. Don’t hesitate to say ‘Hi’ on any platform, just stating a reference of where did you find my profile.