ADR-009: Use Redis and BullMQ for Background Processing
Status
Accepted
Date
YYYY-MM-DD
Context
Chilarai requires support for background and scheduled processing.
Examples include:
- Fee Generation
- Late Fee Processing
- Email Notifications
- SMS Notifications
- Document Processing
- Future Integrations
- Scheduled Maintenance Tasks
The platform requires:
- Reliable execution
- Retry support
- Delayed execution
- Scheduled execution
- Operational visibility
- Scalability
The platform should avoid introducing multiple background processing mechanisms.
Using different frameworks for:
- Scheduled Jobs
- Background Jobs
- Delayed Jobs
would increase implementation complexity and operational overhead.
Decision
Chilarai will use Redis and BullMQ as the standard platform for background processing.
Redis will serve as:
- Queue Backend
- Future Cache Provider
BullMQ will serve as:
- Job Queue
- Background Worker Framework
- Delayed Task Engine
- Scheduled Task Engine
All asynchronous and scheduled processing must be implemented using BullMQ.
The platform will not use NestJS Scheduler for production scheduling workloads.
Rationale
Single Execution Model
Using a single framework for:
- Scheduled Jobs
- Background Jobs
- Delayed Jobs
reduces architectural complexity.
Developers only need to understand one processing model.
Reliability
BullMQ provides:
- Persistent Jobs
- Retry Handling
- Delayed Execution
- Failure Recovery
Jobs are not lost when application instances restart.
Operational Visibility
BullMQ provides visibility into:
- Pending Jobs
- Running Jobs
- Failed Jobs
- Retried Jobs
This simplifies troubleshooting and operations.
Scalability
Workers may be scaled independently from API instances.
Future workloads can be distributed without redesigning business logic.
Redis Reuse
Redis provides additional future capabilities:
- Caching
- Distributed Locks
- Rate Limiting
The platform avoids introducing multiple technologies for similar concerns.
Scheduled Processing
Scheduled tasks must be implemented using BullMQ repeatable jobs.
Examples:
- Daily Late Fee Processing
- Daily Notifications
- Nightly Cleanup Jobs
- Report Generation
The platform will not use NestJS Scheduler as a primary scheduling mechanism.
Background Processing
Background jobs should be used for operations that are:
- Long Running
- Resource Intensive
- Batch Oriented
- Non-Blocking
Examples:
- Fee Generation
- Document Processing
- Notification Delivery
- Future Integration Synchronization
Domain Events
BullMQ is not a replacement for Domain Events.
Domain Events remain in-process communication mechanisms.
Examples:
- StudentCreated
- AdmissionConverted
- EnrollmentCreated
- PaymentReceived
Domain Events should use NestJS EventEmitter.
Background jobs should only be introduced when asynchronous execution is required.
Consequences
Positive
- Single background processing framework
- Reliable job execution
- Retry support
- Delayed processing support
- Scheduled processing support
- Operational visibility
- Scalable architecture
- Future caching capability through Redis
Negative
- Additional Redis dependency
- Additional operational component
- Worker monitoring required
Alternatives Considered
NestJS Scheduler
Pros:
- Simple
- Built into NestJS
Cons:
- No persistent jobs
- No retries
- Limited operational visibility
- Separate execution model
Decision:
Rejected.
Synchronous Execution Only
Pros:
- Simpler architecture
Cons:
- Long-running requests
- Poor scalability
- Reduced reliability
Decision:
Rejected.
Separate Message Broker
Examples:
- RabbitMQ
- Azure Service Bus
Pros:
- Advanced messaging features
Cons:
- Additional operational complexity
- Unnecessary for MVP
Decision:
Deferred.
May be reconsidered when microservices are introduced.
Implementation Notes
Background processing components belong in the Data layer.
Example:
shared/data/jobs
├── queues
├── workers
├── schedulers
└── processors
Business modules should enqueue jobs through abstractions.
Workers should execute application use cases rather than containing business logic.
Decision Summary
Chilarai will standardize on Redis and BullMQ for all background and scheduled processing.
NestJS EventEmitter will continue to be used for in-process domain