Node.js TypeScript Express MongoDB Razorpay
Course Flow

Table of Contents

This is a list of all the sections in this post. Click on any of them to jump to that section.

Description

Course Flow is a backend-first Learning Management System (LMS) built to support real-world educational platforms. The system handles user authentication, course management, payments, media uploads, and notifications with a strong focus on security, scalability, and maintainability.

The project is structured using clean architecture principles, separating routing, validation, business logic, and data access to ensure long-term extensibility and team scalability.

Tech Stack

  • Runtime: Node.js
  • Language: TypeScript
  • Framework: Express.js
  • Database: MongoDB with Mongoose ODM
  • Authentication: JWT (access & refresh tokens)
  • File Storage: Cloudinary
  • Payments: Razorpay, Stripe
  • Email: Resend
  • Validation: Zod
  • Logging: Winston
  • Security: Helmet, Rate Limiting, HPP, XSS protection

Key Features

  • Role-Based Authentication — Secure JWT-based auth for students, instructors, and admins.
  • Course Management APIs — Create, update, publish, and manage courses with structured data models.
  • Payment Integration — Secure course purchases using Razorpay and Stripe with server-side verification.
  • Media Uploads — Cloudinary-based handling for course thumbnails and assets.
  • Email Notifications — Transactional emails for onboarding, payments, and system events.
  • Robust Validation Layer — Strong request validation using Zod schemas.
  • Centralized Logging — Structured logging with Winston for easier debugging and monitoring.

Architecture & API Flow

The backend follows a layered architecture to keep responsibilities clear:

  1. Routes — Define API endpoints
  2. Validations — Validate request payloads with Zod
  3. Controllers — Handle HTTP-level logic
  4. Services — Contain core business logic
  5. Models — Interact with MongoDB via Mongoose

This separation ensures cleaner code, easier testing, and safer refactors.

Challenges & Solutions

1. Designing a Scalable Backend Structure

Challenge: Preventing tight coupling as the feature set grows.

Solution: Adopted a controller–service–model pattern with strict boundaries, enabling independent feature development and easier maintenance.


2. Securing APIs Against Common Attacks

Challenge: Protecting the system from brute force, injection, and malformed requests.

Solution: Implemented layered security using Helmet, rate limiting, input sanitization, HPP protection, and strict schema validation with Zod.


3. Reliable Payment Verification

Challenge: Ensuring payment authenticity and preventing fraud.

Solution: Used server-side payment verification for Razorpay and Stripe webhooks before granting course access.


4. Handling File Uploads at Scale

Challenge: Efficiently storing and serving media without overloading the backend.

Solution: Offloaded uploads to Cloudinary, keeping the backend stateless and performant.

What I Learned

  • Designing production-grade backend architectures with TypeScript and Express.
  • Implementing secure authentication and payment flows.
  • Writing defensive APIs with strong validation and security layers.
  • Structuring large Node.js codebases for scalability and long-term maintainability.