A backend-focused, production-style notification system designed using asynchronous processing and message queues.
The system supports Email, SMS, and Push notifications with built-in reliability mechanisms.
- Asynchronous notification processing using RabbitMQ
- Supports multiple channels: Email, SMS, Push
- Retry mechanism with configurable attempts
- Dead Letter Queue (DLQ) for failed messages
- Idempotent consumers to prevent duplicate delivery
- Manual retry from DLQ for operational recovery
- Structured logging for retries, failures, and DLQ events
- Horizontally scalable worker architecture
- Persistent notification status tracking in database
Client
↓
Notification API
↓
RabbitMQ (notifications queue)
↓
Email Worker | SMS Worker | Push Worker
↓
Database (Status Tracking)
- Backend: Node.js, Express.js
- Messaging: RabbitMQ
- Database: MySQL
- Infra: Docker
- Email: Nodemailer
- SMS: Twilio
- Push: Firebase Cloud Messaging (FCM)
- Testing: Postman, k6
- Logging: Structured console logs
- Client sends notification request to API
- API validates request and stores metadata in DB
- Message is published to RabbitMQ
- Channel-specific worker consumes the message
- On failure → retry queue
- After max retries → Dead Letter Queue (DLQ)
- Manual replay from DLQ supported
- Automatic retries using RabbitMQ TTL queues
- Messages exceeding retry limit are routed to DLQ
- DLQ messages can be manually re-queued
- All retry and DLQ events are logged
- Database-backed idempotency checks
- Prevents duplicate notifications during retries or crashes
- Safe at-least-once message delivery handling
- Logs notification lifecycle events:
- Retry attempts
- DLQ routing
- Manual replays
- Helps in debugging and operational monitoring
- Multiple workers can be run per channel
- RabbitMQ automatically load-balances messages
- Designed to scale horizontally without code changes
- Load tested with 10,000+ concurrent API requests using k6
- Requests were accepted without API crashes or data loss
- Messages were queued reliably in RabbitMQ under burst traffic
- Workers processed messages asynchronously without blocking the API
- Notification states remained consistent in MySQL (
PENDING → SENT / FAILED) - Queue depth, delivery rate, and retries were verified via RabbitMQ dashboard
Note: Tests were performed in a controlled local environment to validate system behavior under load.
- Node.js
- Docker
- RabbitMQ
docker run -d \
--name rabbitmq \
-p 5672:5672 \
-p 15672:15672 \
rabbitmq:3-managementnode src/server.jsnode src/workers/email.worker.js
node src/workers/sms.worker.js
node src/workers/push.worker.jsThis section contains real execution outputs and validation evidence from the system.
All screenshots are taken from actual test runs and local deployments.


