Skip to main content

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
  • pg PostgreSQL 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

  • Email
  • SMS