A microservices-based notification system built with NestJS that sends emails and push notifications using separate services. Services communicate asynchronously through RabbitMQ message queues.
This project implements a distributed notification system with the following services:
- API Gateway Service: Entry point for all notification requests, handles authentication, validation, and routing
- User Service: Manages user contact info, preferences, and authentication
Built with NestJS, PostgreSQL, Redis, and RabbitMQ.
-
API Gateway Service
- Request validation and authentication
- Routes messages to appropriate queues (email/push)
- Tracks notification status via Redis
- Rate limiting per user
- Idempotency using request IDs
-
User Service
- User registration and authentication (JWT)
- User preferences management
- PostgreSQL database for user data
- REST API for user operations
-
Technical Concepts Implemented
- Message Queue (RabbitMQ)
- Caching (Redis)
- Idempotency
- Rate Limiting
- Health Checks
- CI/CD Pipeline
┌─────────────────┐
│ API Gateway │
│ (Port 3000) │
└────────┬────────┘
│
┌────┴─────┐
▼ ▼
┌─────────┐ ┌──────────┐
│ Redis │ │PostgreSQL│
└─────────┘ └──────────┘
│
┌────┴─────────────┐
▼ ▼
┌──────────┐ ┌──────────┐
│Email Queue│ │Push Queue│
└──────────┘ └──────────┘
│
▼
┌─────────────┐
│Failed Queue │
└─────────────┘
- Node.js (v20 or higher)
- Docker and Docker Compose
- PostgreSQL (or use Docker)
- Redis (or use Docker)
- RabbitMQ (or use Docker)
git clone <repository-url>
cd notification-systemnpm installCreate a .env file in the root directory:
cp .env.example .envUpdate the .env file with your configuration:
# Application
NODE_ENV=development
PORT=3000
# Database
USER_DB_HOST=localhost
USER_DB_PORT=5432
USER_DB_USERNAME=postgres
USER_DB_PASSWORD=postgres
USER_DB_NAME=user_service
# Redis
REDIS_HOST=localhost
REDIS_PORT=6379
# RabbitMQ
RABBITMQ_URL=amqp://guest:guest@localhost:5672
# JWT
JWT_SECRET=your-secret-key-change-this-in-production
JWT_EXPIRES_IN=1d# Start all services
docker-compose up -d
# View logs
docker-compose logs -f
# Stop services
docker-compose down# Start PostgreSQL, Redis, and RabbitMQ
docker-compose up -d postgres redis rabbitmq
# Development mode with hot reload
npm run start:dev
# Production mode
npm run build
npm run start:prodOnce the application is running, visit:
- Swagger Documentation: http://localhost:3000/api/docs
- Health Check: http://localhost:3000/health
- RabbitMQ Management: http://localhost:15672 (guest/guest)
# Register a new user
POST /api/v1/users
{
"name": "John Doe",
"email": "user@example.com",
"password": "SecurePassword123!",
"push_token": "device_token",
"preferences": {
"email": true,
"push": true
}
}
# Login
POST /api/v1/auth/login
{
"email": "user@example.com",
"password": "SecurePassword123!"
}# Create notification (requires JWT token)
POST /api/v1/notifications
Authorization: Bearer <token>
{
"notification_type": "email",
"user_id": "uuid",
"template_code": "welcome_email",
"variables": {
"name": "John Doe",
"link": "https://example.com/verify"
},
"request_id": "req_123456789",
"priority": 1
}
# Get notification status
GET /api/v1/notifications/:id
Authorization: Bearer <token># Get all users (paginated)
GET /api/v1/users?page=1&limit=10
Authorization: Bearer <token>
# Get user by ID
GET /api/v1/users/:id
Authorization: Bearer <token>
# Update user
PATCH /api/v1/users/:id
Authorization: Bearer <token>
# Delete user
DELETE /api/v1/users/:id
Authorization: Bearer <token># Unit tests
npm run test
# E2E tests
npm run test:e2e
# Test coverage
npm run test:covThe project includes a GitHub Actions workflow that:
- Lint: Runs ESLint and format checking
- Test: Runs unit tests and generates coverage
- Build: Builds Docker image and pushes to registry
- Deploy: Deploys to staging/production based on branch
SSH_PRIVATE_KEY: SSH key for server accessSERVER_HOST: Production server hostnameSERVER_USER: SSH usernameSTAGING_HOST: Staging server hostnameSTAGING_USER: Staging SSH username
src/
├── common/
│ ├── decorators/
│ ├── filters/
│ ├── guards/
│ ├── interceptors/
│ ├── interfaces/
│ └── utils/
├── config/
│ ├── database.config.ts
│ ├── redis.config.ts
│ └── rabbitmq.config.ts
├── api-gateway/
│ ├── controllers/
│ ├── dto/
│ ├── services/
│ └── api-gateway.module.ts
├── user/
│ ├── controllers/
│ ├── dto/
│ ├── entities/
│ ├── services/
│ └── user.module.ts
└── main.ts
Exchange: notifications.direct
├── email.queue → Email Service
├── push.queue → Push Service
└── failed.queue → Dead Letter Queue
All API responses follow this format:
{
"success": true,
"message": "Request successful",
"data": {},
"meta": {
"total": 100,
"limit": 10,
"page": 1,
"total_pages": 10,
"has_next": true,
"has_previous": false
}
}- Handle 1,000+ notifications per minute
- API Gateway response under 100ms
- 99.5% delivery success rate
- Supports horizontal scaling
- Framework: NestJS
- Language: TypeScript
- Database: PostgreSQL
- Cache: Redis
- Message Queue: RabbitMQ
- Authentication: JWT
- Validation: class-validator
- Documentation: Swagger/OpenAPI
- Containerization: Docker
- Fork the repository
- Create a feature branch
- Commit your changes
- Push to the branch
- Create a Pull Request
This project is licensed under the MIT License.