Backend Architecture
Purpose
This document describes the backend architecture of Chilarai.
It defines:
- Architectural Style
- Module Organization
- Data Access Patterns
- Inter-Module Communication
- Authorization Model
- Background Processing
- Storage Strategy
- Integration Approach
The backend is designed to support both:
- Multi-tenant SaaS deployments
- Self-hosted school deployments
while maintaining simplicity, modularity, and operational efficiency.
Technology Stack
Framework
- NestJS
Database
- PostgreSQL
- Drizzle ORM
pgPostgreSQL driver- Drizzle Kit migrations
Authentication
- Keycloak
Background Processing
- Redis
- BullMQ
Object Storage
- MinIO
Validation
- Zod
API Style
- REST
Architectural Style
Modular Monolith
Chilarai uses a Modular Monolith architecture.
The application is deployed as a single backend service.
Business capabilities are organized into independent modules.
Examples:
- Identity
- School
- Admission
- Student
- Academic
- Staff
- Attendance
- Fees
Modules communicate through well-defined boundaries while remaining within a single deployable application.
Architectural Principles
Business First
Business capabilities drive module boundaries.
Modules are organized around business domains rather than technical concerns.
Explicit Boundaries
Modules communicate through services and domain events.
Modules must not directly access another module's persistence layer.
Single Source of Truth
Each module owns its data and business rules.
Ownership is explicit.
Technology Isolation
Business logic should remain independent of:
- Database technology
- Object storage provider
- Identity provider
- External integrations
Implementation details remain isolated in the Data layer.
Simplicity Over Distribution
The platform favors a Modular Monolith over Microservices.
Distributed systems complexity is intentionally avoided during early stages of product development.
Module Structure
Each module follows a consistent structure.
<module>
├── domain
├── application
├── data
└── api
Domain Layer
The Domain layer contains business concepts and rules.
Examples:
- Entities
- Value Objects
- Domain Rules
- Repository Contracts
- Domain Events
The Domain layer must not depend on:
- NestJS
- PostgreSQL
- Redis
- MinIO
- Keycloak
The Domain layer represents the core business model.
Application Layer
The Application layer contains use cases and orchestration logic.
Examples:
- Create Student
- Promote Student
- Approve Admission
- Generate Fees
Responsibilities:
- Execute business workflows
- Coordinate domain objects
- Manage transactions
- Raise domain events
The Application layer implements business operations.
Data Layer
The Data layer contains all persistence and integration concerns.
Examples:
- PostgreSQL Repositories
- Object Storage Providers
- Keycloak Clients
- Event Publishers
- Redis Clients
- Notification Providers
The Data layer implements contracts defined by the Domain and Application layers.
Examples:
StudentRepository
↓
DrizzleStudentRepository
StorageProvider
↓
MinioStorageProvider
API Layer
The API layer contains external entry points.
Examples:
- REST Controllers
- Request DTOs
- Response DTOs
- Validation
- Authorization Guards
Responsibilities:
- Receive requests
- Validate inputs
- Invoke application use cases
- Return responses
Business rules should not be implemented in the API layer.
Core Modules
Identity Module
Responsibilities:
- User Management
- Authentication Integration
- School Context Resolution
- Membership Resolution
Owned Entities:
- User
- SchoolMembership
School Module
Responsibilities:
- School Management
- School Configuration
- Academic Year Management
Owned Entities:
- School
- AcademicYear
Admission Module
Responsibilities:
- Admission Lifecycle
- Admission Review
- Admission Conversion
Owned Entities:
- Admission
Student Module
Responsibilities:
- Student Management
- Enrollment Management
- Academic Progression
Owned Entities:
- Student
- StudentEnrollment
Academic Module
Responsibilities:
- Class Management
- Section Management
- Subject Management
- Teacher Assignment Management
Owned Entities:
- Class
- Section
- Subject
- ClassSubject
- SectionTeacherAssignment
- SubjectTeacherAssignment
Staff Module
Responsibilities:
- Staff Management
- Employment Information
Owned Entities:
- Staff
Attendance Module
Responsibilities:
- Attendance Tracking
- Attendance Events
- Attendance Reporting
Owned Entities:
- Attendance
- AttendanceEvent
Fees Module
Responsibilities:
- Fee Structures
- Student Fees
- Payments
- Fee Policies
- Fee Adjustments
Owned Entities:
- FeeStructure
- FeeComponent
- StudentFee
- FeeAdjustment
- FeeCharge
- Payment
Database Architecture
Database Strategy
Chilarai uses a single PostgreSQL database.
All modules share the same database.
Separate databases per module are not used.
Data Ownership
Although modules share a database, each module owns its tables.
Examples:
students
student_enrollments
admissions
staff
attendances
payments
Modules must not directly manipulate another module's data through repository access.
Transaction Management
PostgreSQL transactions are used for multi-step business operations.
Example:
Admission Approved
↓
Create Student
↓
Create Enrollment
↓
Generate Fees
These operations must succeed or fail together.
Inter-Module Communication
Service-Based Communication
Modules communicate through application services.
Example:
Fees Module
↓
Student Service
Modules must not use repositories from other modules.
Domain Events
Modules may communicate through domain events.
Examples:
- AdmissionConverted
- StudentCreated
- EnrollmentCreated
- PaymentReceived
Domain events support loose coupling while remaining inside the monolith.
Authorization Model
School Context
All requests operate within an active School context.
The selected School determines:
- Data Visibility
- Feature Access
- Administrative Permissions
Authorization Flow
JWT
↓
User
↓
School Membership
↓
Roles
↓
Permissions
Authorization is membership-driven.
Permissions are not assigned directly to Users.
Background Processing
Technology
- Redis
- BullMQ
BullMQ is the standard platform for:
- Background Jobs
- Delayed Jobs
- Scheduled Jobs
The platform does not use multiple scheduling mechanisms.
Typical Workloads
Examples:
- Fee Generation
- Late Fee Processing
- Notification Delivery
- Document Processing
- Future Integrations
Execution Model
Business requests remain synchronous.
Long-running workloads are delegated to BullMQ workers.
Example:
Generate Fees
↓
Create Job
↓
Immediate Response
Worker
↓
Process Fees
Object Storage
Technology
- MinIO
Object storage is accessed through a StorageProvider abstraction.
Storage Strategy
PostgreSQL stores:
- Object Keys
- Metadata
PostgreSQL does not store:
- Images
- PDFs
- Binary Documents
File Types
Examples:
- Student Photos
- Staff Photos
- Admission Documents
- Certificates
- School Assets
Security
All buckets are private.
Files are accessed through temporary pre-signed URLs.
Search Strategy
Initial Approach
Search is implemented using PostgreSQL capabilities.
Examples:
- Student Search
- Admission Search
- Staff Search
Dedicated search infrastructure is not introduced during initial development.
External Integrations
Integration Principle
External systems must be accessed through abstractions.
Examples:
IdentityProvider
StorageProvider
NotificationProvider
PaymentProvider
Business modules should not depend on vendor-specific SDKs.
Initial Implementations
IdentityProvider
- Keycloak
StorageProvider
- MinIO
NotificationProvider
- SMS