Designing a Scalable Notification System: Models, Services, and Subscriptions
This article details the design and implementation of a notification system, covering data models for notifications, user queues, subscription configurations, and a service layer with methods for creating, pulling, and managing announcements, reminders, and messages.
This article continues from the previous part, focusing on the implementation of a messaging system to inspire readers.
Model Design
Notify
id: {type: 'integer', primaryKey: true} // primary key
content: {type: 'text'} // message content
type: {type: 'integer', required: true, enum: [1, 2, 3]} // 1: Announce, 2: Remind, 3: Message
target: {type: 'integer'} // target ID
targetType: {type: 'string'} // target type
action: {type: 'string'} // action type for reminders
sender: {type: 'integer'} // sender ID
createdAt: {type: 'datetime', required: true}
Save Remind
For reminder records we need target, targetType to identify the associated object, and action to record the related action. Example: a reminder "Xiao Ming liked an article" would be stored as:
target = 123 // article ID
targetType = 'post' // indicates the target is an article
sender = 123456 // Xiao Ming's user ID
Save Announce and Message
Announcements and messages use the content field and do not require target, targetType, or action.
UserNotify
id: {type: 'integer', primaryKey: true} // primary key
isRead: {type: 'boolean', required: true}
user: {type: 'integer', required: true} // owner of the notification
notify: {type: 'integer', required: true} // reference to Notify
createdAt: {type: 'datetime', required: true}
UserNotify stores a user's notification queue and links to a specific Notify record. It is created via two pathways:
When iterating the Subscription table to pull announcements and reminders.
Immediately after a new Message is created.
Subscription
target: {type: 'integer', required: true} // target ID
targetType: {type: 'string', required: true} // target type
action: {type: 'string'} // subscription action, e.g., comment, post, update
user: {type: 'integer'} // subscriber
createdAt: {type: 'datetime', required: true}
Subscriptions define which actions on which targets a user wishes to be notified about. Example: "Xiao Ming follows comments on product A" translates to:
target = 123 // product A ID
targetType = 'product'
action = 'comment'
user = 123 // Xiao Ming's ID
SubscriptionConfig
action: {type: 'json', required: true} // user settings
user: {type: 'integer'}
Different users may have different subscription preferences. The default configuration is:
{
'comment': true,
'like': true
}In this model, targetType and action can be extended, e.g., adding actions like hate (downvote) or update .
NotifyConfig
targetType: {
PRODUCT: 'product', // product
POST: 'post' // article
}action: {
COMMENT: 'comment', // comment
LIKE: 'like' // like
}reasonAction: {
'create_product': ['comment', 'like'],
'like_product': ['comment'],
'like_post': ['comment']
}defaultSubscriptionConfig: {
'comment': true,
'like': true
}Service Layer NotifyService
NotifyService provides the following methods:
createAnnounce(content, sender)
createRemind(target, targetType, action, sender, content)
createMessage(content, sender, receiver)
pullAnnounce(user)
pullRemind(user)
subscribe(user, target, targetType, reason)
cancelSubscription(user, target, targetType)
getSubscriptionConfig(userID)
updateSubscriptionConfig(userID)
getUserNotify(userID)
read(user, notifyIDs)
Method Logic
createAnnounce(content, sender)
Insert a new announcement record into the Notify table.
createRemind(target, targetType, action, sender, content)
Insert a new reminder record into the Notify table.
createMessage(content, sender, receiver)
Insert a new message record into the Notify table.
Insert a corresponding UserNotify record linking to the new Notify.
pullAnnounce(user)
Retrieve the most recent announcement creation time (lastTime) from UserNotify.
Use lastTime as a filter to query new announcements from Notify.
Create UserNotify entries for the fetched announcements.
pullRemind(user)
Fetch the user's subscription records.
For each subscription, use target, targetType, action, and createdAt to query matching Notify records (subscription time must precede reminder creation).
Retrieve the user's SubscriptionConfig; fall back to the default if absent.
Filter the queried Notify records according to the subscription configuration.
Create UserNotify entries for the filtered notifications.
subscribe(user, target, targetType, reason)
Lookup NotifyConfig using the reason to obtain the associated action set.
For each action, create a Subscription record.
cancelSubscription(user, target, targetType)
Delete the Subscription record(s) matching the user, target, and targetType.
getSubscriptionConfig(userID)
Query the SubscriptionConfig table for the user's settings.
updateSubscriptionConfig(userID)
Update the user's SubscriptionConfig record.
getUserNotify(userID)
Retrieve the list of notifications for the user.
read(user, notifyIDs)
Set the isRead attribute to true for the specified notifications.
Sequence Diagrams
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
21CTO
21CTO (21CTO.com) offers developers community, training, and services, making it your go‑to learning and service platform.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
