Skip to content

Server-Side System Architecture (NestJS Backend)

Server-Side System Architecture (NestJS Backend)

Executive Summary

The Learnille Server (server/) is an enterprise-grade NestJS RESTful API backend engineered for multi-tenant online learning, 1-on-1 expert consultations, real-time presence, wallet payouts, and multi-currency transaction processing.


🏛 1. High-Level Server System Diagram

+------------------------------------+
| Client Apps (Student, Admin, |
| Instructor, Consultant) |
+-----------------+------------------+
|
HTTPS / REST / WebSockets
|
v
+---------------------------------------------------------------------------------------------------+
| NESTJS SERVER BACKEND (`server/`) |
| |
| +---------------------------------------------------------------------------------------------+ |
| | ENTRY PIPELINE: Helmet -> Cors -> CookieParser -> ThrottlerGuard -> RequestLoggerMiddleware | |
| +----------------------------------------------+----------------------------------------------+ |
| | |
| +----------------------------------------------v----------------------------------------------+ |
| | GLOBAL INTERCEPTORS & FILTERS: ResponseInterceptor, AllExceptionsFilter, CurrencyConversion | |
| +----------------------------------------------+----------------------------------------------+ |
| | |
| +----------------------------------------------v----------------------------------------------+ |
| | FEATURE MODULE DOMAINS: | |
| | - AuthModule (JWT RS256, Passport, Google/Apple OAuth, CASL RBAC) | |
| | - CourseModule (Curriculum Editor, Sections, Video Progress) | |
| | - ConsultationModule (Availability Calendar, Booking Engine, Slot Resolution) | |
| | - WalletModule & WithdrawalModule (Escrow Hold, NGN Bank Resolution, OTP Verification) | |
| | - ProductModule & ValidationModule (Quality Assurance Queue, State Machine) | |
| | - PaymentModule (Paystack & Flutterwave Gateways, Webhook Verification) | |
| | - OpenSearchModule (Vector Indexing, Full-Text Catalog Search) | |
| | - InstantdbModule (Real-Time Room State & Sync) | |
| | - OutboxModule & BullmqModule (Transactional Outbox Pattern, Async Queues) | |
| | - NotificationModule (Novu Framework & Soketi WebSocket Channels) | |
| +----------------------------------------------+----------------------------------------------+ |
+-------------------------------------------------|-------------------------------------------------+
|
+--------------------+---------------------+--------------------+--------------------+
| | | | |
v v v v v
+--------------+ +--------------+ +--------------+ +--------------+ +--------------+
| Self-Hosted | | Self-Hosted | | Cloudflare | | OpenSearch | | New Relic |
| PostgreSQL | | Redis | | R2 S3 | | Index Engine | | APM & Logs |
| (TypeORM DB) | | (BullMQ) | | (Storage) | | (Vector Srch)| | & Sentry |
+--------------+ +--------------+ +--------------+ +--------------+ +--------------+

🛠 2. Request Handling Pipeline & Lifecycle

When an HTTP request enters the NestJS server, it passes through a deterministic processing chain:

[ Incoming HTTP Request ]
|
v
1. [ Security & Middleware Layer ]
- Helmet (Security headers)
- Cookie Parser
- AppRequestLoggerMiddleware (Pino/Winston request logger)
|
v
2. [ Rate Limiting Guard ]
- ThrottlerGuard (Redis-backed rate limiting with RedisThrottlerStorage)
|
v
3. [ Authentication & Authorization Guards ]
- JwtAuthGuard (Passport JWT RS256/HS256 validation)
- RolesGuard / CASL AbilityGuard (Role checks: STUDENT, INSTRUCTOR, CONSULTANT, ADMIN)
|
v
4. [ DTO Input Validation Pipe ]
- ValidationPipe (class-validator DTO checking with transform: true)
|
v
5. [ Controller Action Handler ]
- Extracts payload via @Body(), user via @CurrentUser()
- Delegates business logic to domain service
|
v
6. [ Interceptors & Exception Filters ]
- CurrencyConversionInterceptor (converts prices dynamically via dynamic header)
- ResponseInterceptor (wraps output into standard { statusCode, message, data } JSON)
- AllExceptionsFilter (catches and formats HTTP and system errors for client & Sentry)
|
v
[ Formatted HTTP Response ]

📦 3. Deep Domain Module Architecture

3.1. Authentication & Security Subsystem (auth/, casl/, crypto/)

  • Token Architecture: RS256 asymmetric key pairs (CryptoModule). Short-lived JWT access tokens + Redis-rotated refresh tokens.
  • Social Login: OAuth flow handling for Google (google/) and Apple (auth/). Account linking endpoints permit attaching social credentials to an existing user account.
  • CASL Role Permissions: Fine-grained access control supporting 4 primary roles (Student, Instructor, Consultant, Admin).

3.2. Course Curriculum Engine (course/, category/)

  • Normalized Curriculum: Supports hierarchical structure: Course -> Section -> Subsection -> Item (Video, Document, Quiz).
  • Progress Tracking: Continuous video timestamp tracking via heartbeat endpoints (/course/video-progress) recalculating student completion percentage dynamically.
  • Category Hierarchy: Category tree mapping supporting parent-child categories, featured flags, and display order batch updating.

3.3. Consultation Booking & Availability (consultation/, consultant/)

  • Dual Mode: Supports ONEOFF (specific single date/time) and RECURRING (weekly interval windows) consultations.
  • Availability Engine: Calculates available time slots dynamically by cross-referencing consultant weekly hours, booked slot reservations, minimum notice buffers (e.g. 2 hours notice required), and timezone offsets.
  • Reschedule Workflow: Multi-party rescheduling protocol allowing students or consultants to propose pending slot changes.

3.4. Escrow, Wallet & Withdrawal System (wallet/, withdrawal/, payments/)

  • Escrow Payment Hold: Funds from course sales or bookings enter pending_hold in provider wallets, releasing to available_balance upon course refund window expiry or consultation completion.
  • Dual Payment Gateways: Paystack and Flutterwave adapters with strict webhook signature verification (x-paystack-signature, Flutterwave hash).
  • Multi-Step Withdrawal Flow:
    1. Add bank account method (/withdrawals/methods). Bank account holder name is resolved via Flutterwave NGN lookup.
    2. Verify account via SMS/email OTP (/withdrawals/methods/verify).
    3. Initiate withdrawal request (/withdrawals/request).
    4. Verify withdrawal with secondary OTP (/withdrawals/:id/verify).
    5. Admin approves and executes automated bank payout (/withdrawals/:id/approve).

3.5. Transactional Outbox & Background Processing (outbox/, bullmq/)

  • Outbox Pattern: Changes to database entities write an outbox event in the same DB transaction (outbox_events).
  • BullMQ Workers: BullMQ worker polls and processes outbox events asynchronously, handling external webhook dispatches, email triggers via Novu, and real-time Soketi broadcasts with automatic retries and dead-letter queues.

3.6. Search & Vector Engine (opensearch/)

  • Catalog Indexing: Auto-indexes published courses and consultations into OpenSearch.
  • Vector Search: Supports hybrid keyword search and semantic vector embeddings for recommendations and fast discovery.

🗄 4. Database & Persistence Standards

  • Primary Database: PostgreSQL accessed via TypeORM.
  • Naming Standard: All database columns use snake_case transformation (created_at, user_id, is_published).
  • Migrations: TypeORM migration scripts (server/src/migrations/) maintain database schema changes. Direct schema alteration in production is strictly prohibited.

📊 5. Server Configuration & Observability

  • Centralized Config: ConfigModule validates all environment variables on boot via validateConfig in server/src/config.ts.
  • Monitoring: Integrated with New Relic APM for transaction tracing, New Relic Log Enrichment for Winston logs, and Sentry for real-time exception reporting.
  • Health Diagnostics: HealthModule powered by NestJS Terminus monitoring DB connection status, Redis availability, and host memory usage (/health).