A scalable, event-driven Notification Service built with ASP.NET Core.
The system supports:
- Topic-based notifications (delivered to subscribed users)
- Single-user notifications
- Multi-channel delivery
- User preferences
- Reliable message processing using RabbitMQ and Redis (cache-aside pattern)
This project demonstrates how to design and implement a production-ready notification system using Clean Architecture principles.
It focuses on:
- Reliability
- Scalability
- Extensibility
- High availability
- JWT Authentication & Role-Based Authorization
- Admin Notification Management (filtering, sorting, scheduling)
- User Inbox with read/unread tracking
- External API Integration (API key secured)
- Topic-Based Subscriptions (or single-user delivery)
- User Channel & Category Preferences
- Multi-Channel Delivery (Email & In-App)
- RabbitMQ-based asynchronous processing
- Retry Mechanism & Dead-Letter Queue support
- Real-time delivery ready (SignalR integration ready)
- Redis caching with cache-aside pattern
- Caches topic subscribers
- Caches categories
- Caches user preferences
- Falls back to database when cache is unavailable
- Clean Architecture with Domain Events
The system must support sending notifications through:
- SMS
- Push notifications
- In-app messages
- Topic-based notifications (delivered to all subscribed users)
- Single-user notifications (direct messages)
- Scheduled notifications
The system must allow notifications to be scheduled for future delivery.
The system must ensure that users receive only a limited number of promotional notifications within a defined period to prevent spam.
The system must handle notification delivery failures and retry when necessary.
The system should handle millions of notifications per minute and support millions of concurrent users.
The system must ensure minimal downtime and continue delivering notifications during partial failures.
The system must guarantee at-least-once delivery, with support for exactly-once semantics where applicable.
The system follows an event-driven, decoupled architecture where external services publish notifications via API (secured by API Key).
Notifications are processed through domain events and background jobs, then dispatched to RabbitMQ for asynchronous delivery.
Channel-specific consumers (Email, In-App/SignalR) process messages and update delivery status.
Redis is used for caching (cache-aside pattern) and database as source of truth.
Dead-letter queues and retry mechanisms ensure reliability and fault tolerance.
- ASP.NET Core
- RabbitMQ
- Redis (Cache-Aside Pattern)
- SQL Server / EF Core
- SignalR
- Clean Architecture
Make sure the following tools are installed:
- .NET 8 SDK
- SQL Server
- Docker Desktop
- Git
- Postman (optional)
git clone https://github.com/your-username/notification-service.git
cd notification-servicedocker run -d \
--name notification-redis \
-p 6380:6379 \
redisRedis is used for cache-aside pattern implementation.
docker run -d \
--name notification-rabbitmq \
-p 5672:5672 \
-p 15672:15672 \
rabbitmq:3-managementRabbitMQ Management UI:
http://localhost:15672
Default credentials:
Username: guest
Password: guest
"RabbitMq": {
"Connection": {
"HostName": "localhost",
"Port": 5672,
"UserName": "guest",
"Password": "guest"
},
"Topology": {
"MainExchange": "notifications.dispatch",
"DeadLetterExchange": "notifications.dlx",
"EmailQueue": "notifications-email",
"InAppQueue": "notifications-inapp",
"PushQueue": "notifications-push",
"SmsQueue": "notifications-sms",
"EmailRoutingKey": "channel.email",
"InAppRoutingKey": "channel.inapp",
"PushRoutingKey": "channel.push",
"SmsRoutingKey": "channel.sms"
}
}Update the connection string in:
src/Project.Api/appsettings.json
Example:
"ConnectionStrings": {
"DefaultConnection": "Server=.;Database=NotificationServiceDb;Integrated Security=true;TrustServerCertificate=True;"
}Make sure you are in the solution root directory, then run:
dotnet ef database update --project src/Project.Infrastructure --startup-project src/Project.ApiIf EF tools are not installed:
dotnet tool install --global dotnet-efThis project uses Mailtrap for development email testing.
Update SmtpOptions in appsettings.json:
"SmtpOptions": {
"Host": "sandbox.smtp.mailtrap.io",
"Port": 587,
"EnableSsl": true,
"Username": "<your-username>",
"Password": "<your-password>"
}Steps:
- Create a Mailtrap account
- Create a sandbox inbox
- Replace credentials in
appsettings.json
Update JWT settings in appsettings.json:
"JwtOptions": {
"Issuer": "https://localhost:7030",
"Audience": "Audience",
"SecretKey": "<your-secret-key>",
"ExpirationInHours": "1"
}Use environment variables or .NET User Secrets instead.
Restore dependencies:
dotnet restoreBuild the solution:
dotnet buildRun the API:
dotnet run --project src/Project.ApiThe API will be available at:
https://localhost:7030
Swagger UI:
https://localhost:7030/swagger
Available at:
https://localhost:xxxx/swagger
The OpenAPI JSON file is available in:
docs/openapi.json
Import the collection from:
docs/notification-service.postman_collection.json
docker-compose up --build- SMS Integration
- Push Notifications
- Kubernetes Deployment
- Observability (Prometheus & Grafana)
- Distributed Tracing
This project is licensed under the MIT License — see the LICENSE file for details.


