How to Store and Redeliver Offline Notifications Using RabbitMQ (Offline Notifications RabbitMQ)
In modern notification systems, it is common for some users to be offline when notifications are sent. This is where offline notifications RabbitMQ becomes important: storing notifications for disconnected users and automatically redelivering them when they reconnect.
In this guide, you will learn how to design a notification system that handles offline users with RabbitMQ, including:
- User presence detection (online vs offline)
- Storing notifications for offline users
- Resending notifications when users reconnect
- Architecture best practices for scalability and reliability
Why Use Offline Notifications with RabbitMQ?
Real-time notification systems built with WebSockets or push notifications work well when users are connected, but in practice:
- Users may close the application completely.
- Internet connections can drop unexpectedly.
- Web apps may be closed or browser tabs may freeze.
In these situations, a real-time notification sent only once may be lost. To prevent this, you need to:
- Detect user status (online or offline).
- Store notifications for offline users in persistent storage.
- Redeliver notifications when the user returns.
RabbitMQ is not a database. It is a message broker used to manage the flow of notifications between services while integrating with databases and delivery channels such as WebSockets, push services, and email.
Offline Notification System Architecture Using RabbitMQ
A high-level architecture for offline notifications RabbitMQ typically includes:
- Notification Producer: Any service or microservice generating notifications such as new messages, comments, or alerts.
- RabbitMQ Exchange: Distributes notifications to queues based on routing rules.
- Notification Service: Responsible for:
- Consuming messages from RabbitMQ
- Checking user connection status
- Sending notifications to online users
- Storing notifications for offline users
- Storage Layer: Relational databases, NoSQL databases, or Redis for unread or undelivered notifications.
- Delivery Channels: WebSockets, FCM push notifications, email, or SMS.
How to Detect Whether a User Is Online or Offline
The first step in building an offline notification system is detecting user presence.
1. Track WebSocket Connections
In web and mobile apps using WebSockets:
- When a client opens a WebSocket connection:
- Mark the user as online in a presence system such as Redis.
- When the connection closes:
- Update the user status to offline.
Common storage options:
- Redis using keys like:
user:{id}:status = online/offline - A database table such as:
user_status
2. Use Heartbeats or Ping Checks
If WebSockets are unavailable, you can rely on:
- Periodic API ping requests updating:
last_seen_at - Marking users offline if no activity occurs within a defined time window.
The goal is simple: when the Notification Service consumes a RabbitMQ message, it must answer:
Is this user currently online?
RabbitMQ Queue and Exchange Design for Notifications
Common RabbitMQ patterns for notifications include:
- Topic Exchange for routing by user or notification type
- Direct Exchange for straightforward routing
- Fanout Exchange for broadcast notifications
A simple setup might use:
- Exchange:
notifications.exchange (type topic) - Routing key:
user.<userId>.notification - Shared queue:
notifications.queue
A Notification Service can consume from this queue and decide how each notification should be handled.
Core Logic: When to Send vs Store Notifications
When Notification Service receives a message from RabbitMQ:
- Consume the message payload, for example:
user_id title body type created_at
- Check user presence from Redis or the database.
- If the user is online:
- Send immediately through WebSocket or push notification.
- Optionally store it as unread for history.
- If the user is offline:
- Store it in a table like:
user_notifications - Set status to:
pending or not_delivered
- Send RabbitMQ ACK only after successful storage or delivery.
This makes RabbitMQ a transport layer while persistent storage holds the actual notifications.
Where to Store Offline Notifications
1. Relational Databases (PostgreSQL or MySQL)
Ideal when you need:
- Filtering, sorting, and pagination
- Relationships with users, orders, or posts
user_notifications (
id BIGINT PK,
user_id BIGINT,
title VARCHAR,
body TEXT,
type VARCHAR,
status ENUM('pending','delivered','read'),
created_at TIMESTAMP,
delivered_at TIMESTAMP NULL,
read_at TIMESTAMP NULL
)
2. NoSQL Databases (MongoDB)
Useful when:
- Notification volume is very large
- Payload structure is dynamic
3. Redis or In-Memory Storage
Can be used as a fast temporary layer for recent notifications, with older records migrated into permanent storage.
How to Redeliver Notifications When Users Reconnect
When a user returns:
- Fetch stored notifications created while they were away
- Deliver them immediately
- Update status to
delivered
Scenario 1: WebSocket Reconnection
- User authenticates through WebSocket.
- Call:
fetchPendingNotifications(userId) - Retrieve all notifications with pending status.
- Send them as a batch or stream.
- Update status to delivered with timestamp.
Scenario 2: REST API Retrieval
GET /api/notifications?status=pending
The client calls this endpoint when opening the app or periodically polls for undelivered notifications.
Using RabbitMQ as a Trigger for Redelivery
You can also use RabbitMQ when a user changes from offline to online.
- Presence service emits an event such as:
user.<userId>.status.online - Notification Service consumes the event and:
- Calls:
fetchPendingNotifications(userId) - Delivers all pending notifications
- Updates their status in the database
This makes RabbitMQ part of both:
- Notification production
- Notification recovery
Retries and Dead Letter Queues (DLQ)
Failures may occur when:
- Saving notifications to the database
- Sending through push services or WebSockets
Important reliability mechanisms include:
- Retry mechanisms with exponential backoff
- Dead Letter Queues (DLQ) for messages that repeatedly fail
This prevents message loss and improves fault tolerance.
Important Design Tips for Offline Notifications RabbitMQ
1. Do Not Use RabbitMQ as a Database
RabbitMQ is not long-term storage.
Best practice:
- Consume from the queue
- Store important notification data in a database
- Then acknowledge the message
2. Separate Delivery from Storage
Your Notification Service should have two layers:
- Delivery Layer
- Selects channels like WebSocket, push, or email
- Storage Layer
- Manages statuses such as pending, delivered, and read
This separation improves maintainability and scalability.
3. Plan for Scalability
As traffic grows, consider:
- Splitting queues or using multiple work queues
- Scaling consumers horizontally
- Distributing load across RabbitMQ instances if needed
Example Flow: Offline User Receives Notification Later
- A new message event occurs.
- Chat Service publishes to:
notifications.exchange with routing key: user.123.notification - Notification Service consumes from:
notifications.queue - Presence service reports user 123 is offline.
- Notification is stored in:
user_notifications with status: pending - One hour later the user reconnects.
- Presence updates user to online.
- Notification Service calls:
fetchPendingNotifications(123) - Pending notifications are delivered through WebSocket.
- Status changes to:
delivered
No notification is lost even though the user was offline at send time.
Offline Notifications RabbitMQ in Microservices
In microservices environments, multiple services may generate notifications such as:
Best practice:
- Business services should not send notifications directly.
- They should publish events into RabbitMQ.
- A dedicated Notification Service should consume events and decide:
- Is the user online?
- How should the notification be delivered?
- Should it be stored as an offline notification?
This keeps notification logic centralized and scalable.
Conclusion
Building an offline notifications RabbitMQ system is not simply putting messages in a queue. It requires a complete design involving:
- User presence tracking
- Persistent storage for offline notifications
- RabbitMQ as a reliable messaging layer
- Notification redelivery through WebSockets or APIs
- Retry mechanisms and dead letter queues for reliability
With these principles, you can build a scalable, fault-tolerant notification system that ensures users never miss important notifications, even when they are offline.