Skip to content

NestJS microservices architecture for School Management System with Kafka messaging, role-based authentication, and Prisma ORM

License

Notifications You must be signed in to change notification settings

masabinhok/sms-api

Repository files navigation

SMS API - Microservices Architecture

License: MIT NestJS TypeScript Kafka Prisma

A production-ready school management system built with NestJS, using event-driven microservices architecture with Apache Kafka for inter-service communication and Prisma for database management.

Architecture Overview

┌─────────────────┐
│   API Gateway   │ ← HTTP/REST (Port 3000)
│   (Gateway)     │
└────────┬────────┘
         │ Kafka RPC
         ├─────────────┬─────────────┬─────────────┬─────────────┬─────────────┐
         ▼             ▼             ▼             ▼             ▼             ▼
    ┌────────┐   ┌─────────┐   ┌─────────┐   ┌──────────┐   ┌──────────┐   ┌───────┐
    │  Auth  │   │ Student │   │ Teacher │   │Academics │   │ Activity │   │ Email │
    └────────┘   └─────────┘   └─────────┘   └──────────┘   └──────────┘   └───────┘
        │            │             │              │              │              │
        ▼            ▼             ▼              ▼              ▼              ▼
     [DB]         [DB]          [DB]           [DB]           [DB]          [SMTP]

Microservices

Service Description Port Database
Gateway API Gateway, routing, authentication, public endpoints 3000 PostgreSQL (Public)
Auth User authentication, JWT tokens, password management - PostgreSQL
Student Student profile, enrollment, records - PostgreSQL
Teacher Teacher profile, assignments - PostgreSQL
Academics School, classes, subjects, curriculum - PostgreSQL
Activity School activities, events, attendance - PostgreSQL
Email Email notifications (SMTP) - -

Quick Start

Prerequisites

  • Node.js 20+
  • Docker & Docker Compose
  • Git (optional, for cloning)

That's it! Everything else (Kafka, PostgreSQL, databases) is handled by Docker Compose.

Step 1: Get the Code

Option A: Clone with Git (Recommended)

git clone https://github.com/masabinhok/sms-api.git
cd sms-api

Option B: Download ZIP

  1. Go to https://github.com/masabinhok/sms-api
  2. Click the green "Code" button → "Download ZIP"
  3. Extract and navigate to the folder

Step 2: Automated Setup (Recommended for Reviewers)

For Windows (PowerShell as Admin):

# Enable script execution (first time only)
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser

# Run setup
.\scripts\setup.ps1

For Linux/Mac:

chmod +x scripts/setup.sh
./scripts/setup.sh

This script will:

  • ✅ Install all npm dependencies
  • ✅ Create .env file from template
  • ✅ Start Kafka cluster (3 brokers) + PostgreSQL
  • ✅ Create all databases automatically
  • ✅ Generate Prisma clients
  • ✅ Run all database migrations
  • ✅ Seed sample data (users, academics, teachers, students)

Then start the services:

npm run dev

For detailed step-by-step instructions, see SETUP.md - A complete beginner-friendly guide!

Step 3: Manual Setup (Alternative)

1. Install Dependencies

npm install

2. Start Infrastructure (Kafka + PostgreSQL)

docker-compose up -d

This starts:

  • 3 Kafka brokers (ports 9094, 9095, 9096)
  • Kafka UI (http://localhost:8080)
  • PostgreSQL with all databases (port 5432)

3. Configure Environment Variables

Security Warning: Never commit .env files to version control. Use the provided .env.example as a template.

# Copy the example file
cp .env.example .env

# The default values work with docker-compose!
# No changes needed for local development

⚠️ Email Service Configuration Required: To enable email notifications (password resets, contact inquiries, etc.), you must configure your own SMTP credentials in the .env file:

  • SMTP_HOST, SMTP_PORT, SMTP_USER, SMTP_PASS
  • For Gmail: Enable 2FA and generate an App Password
  • Without email configuration, the email service will start but emails won't be sent

4. Generate Prisma Clients & Run Migrations

# Generate Prisma clients
npx prisma generate --schema=apps/auth/prisma/schema.prisma
npx prisma generate --schema=apps/student/prisma/schema.prisma
npx prisma generate --schema=apps/teacher/prisma/schema.prisma
npx prisma generate --schema=apps/academics/prisma/schema.prisma
npx prisma generate --schema=apps/activity/prisma/schema.prisma
npx prisma generate --schema=apps/gateway/prisma/schema.prisma

# Run migrations
npx prisma migrate deploy --schema=apps/auth/prisma/schema.prisma
npx prisma migrate deploy --schema=apps/student/prisma/schema.prisma
npx prisma migrate deploy --schema=apps/teacher/prisma/schema.prisma
npx prisma migrate deploy --schema=apps/academics/prisma/schema.prisma
npx prisma migrate deploy --schema=apps/activity/prisma/schema.prisma
npx prisma migrate deploy --schema=apps/gateway/prisma/schema.prisma

5. Seed Databases (Optional)

# Seed all databases at once
npm run seed:all

# Or seed individually
npm run seed:auth        # Create sample users (admin, teachers, students, guardians)
npm run seed:academics   # Create school info, classes, subjects
npm run seed:teacher     # Create sample teacher profiles
npm run seed:student     # Create sample student profiles

Default credentials after seeding:

  • Admin: admin@school.edu / Password123!
  • Teacher: john.smith@school.edu / Password123!
  • Student: emma.thompson@student.school.edu / Password123!

6. Start All Services

# Development mode (all services in parallel)
npm run dev

# Or start individually
npm run start:gateway
npm run start:auth
npm run start:student
npm run start:teacher
npm run start:academics
npm run start:activity
npm run start:email

Access Points

Development

Run Individual Services

npm run start:auth        # Auth service
npm run start:student     # Student service
npm run start:teacher     # Teacher service
npm run start:academics   # Academics service
npm run start:activity    # Activity service
npm run start:email       # Email service
npm run start:gateway     # API Gateway

Generate Prisma Client

npx prisma generate --schema=apps/<service>/prisma/schema.prisma

Run Tests

npm run test              # Unit tests
npm run test:watch        # Watch mode
npm run test:cov          # Coverage
npm run test:e2e          # E2E tests

Seed Database

npm run seed:all          # Seed all services
npm run seed:auth         # Seed users only
npm run seed:academics    # Seed academics only
npm run seed:teacher      # Seed teachers only
npm run seed:student      # Seed students only

Key Features

Robust Exception Handling

  • Centralized error handling with custom exception filters
  • Prisma error mapping to HTTP status codes
  • Structured error responses with timestamps and context
  • See EXCEPTION_HANDLING.md

Comprehensive Health Checks

  • /health - Full system health (memory, disk, Kafka)
  • /health/ready - Readiness probe for Kubernetes
  • /health/live - Liveness probe
  • See HEALTH_CHECKS.md

Structured Logging

  • NestJS Logger for services
  • Context-aware logging with service names
  • Production-ready log formatting
  • See LOGGING.md

Password Security

  • Bcrypt hashing (12 rounds)
  • Password validation rules
  • Secure token management
  • See PASSWORD_SECURITY.md

Database Transaction Management

Troubleshooting

Kafka Connection Issues

Problem: Services fail to connect to Kafka brokers

Error: Failed to connect to kafka broker

Solution:

  1. Verify Kafka containers are running: docker-compose ps
  2. Check Kafka broker ports are accessible: localhost:9094,9095,9096
  3. Restart Kafka cluster: docker-compose restart
  4. Check Kafka UI at http://localhost:8080 to verify cluster health

Database Migration Errors

Problem: Prisma migration fails

Error: P1001: Can't reach database server

Solution:

  1. Verify PostgreSQL is running and accessible
  2. Check database URL in .env file
  3. Ensure database exists: CREATE DATABASE academics;
  4. Test connection: npx prisma db pull --schema=apps/academics/prisma/schema.prisma

Port Already in Use

Problem: Gateway fails to start on port 3000

Error: listen EADDRINUSE: address already in use :::3000

Solution:

  1. Find process using port: Get-Process -Id (Get-NetTCPConnection -LocalPort 3000).OwningProcess
  2. Kill the process or change PORT in .env

Prisma Client Generation Issues

Problem: Module not found errors for Prisma client

Error: Cannot find module '@prisma/client'

Solution:

# Regenerate Prisma clients for all services
npx prisma generate --schema=apps/auth/prisma/schema.prisma
npx prisma generate --schema=apps/student/prisma/schema.prisma
npx prisma generate --schema=apps/teacher/prisma/schema.prisma
npx prisma generate --schema=apps/academics/prisma/schema.prisma
npx prisma generate --schema=apps/activity/prisma/schema.prisma

Service Not Responding

Problem: Microservice doesn't respond to requests Solution:

  1. Check service logs for errors
  2. Verify Kafka consumer group is active (check Kafka UI)
  3. Ensure service is registered with correct topic name
  4. Restart the specific service

API Usage Examples

Public Endpoints (No Authentication Required)

# Submit contact inquiry
curl -X POST http://localhost:3000/api/v1/public/contact-inquiry \
  -H "Content-Type: application/json" \
  -d '{
    "name": "John Doe",
    "email": "john@example.com",
    "phone": "+1-555-0123",
    "subject": "Admission Information",
    "message": "I would like to know more about the admission process."
  }'

# Schedule campus visit
curl -X POST http://localhost:3000/api/v1/public/schedule-visit \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Jane Smith",
    "email": "jane@example.com",
    "phone": "+1-555-0456",
    "preferredDate": "2025-12-15",
    "preferredTime": "10:00 AM",
    "numberOfVisitors": "2",
    "notes": "Interested in science facilities"
  }'

# Request brochure
curl -X POST http://localhost:3000/api/v1/public/brochure-request \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Mike Johnson",
    "email": "mike@example.com",
    "phone": "+1-555-0789"
  }'

Authentication

# Register a new user
curl -X POST http://localhost:3000/api/v1/api/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@school.com",
    "password": "SecurePass123!",
    "role": "ADMIN"
  }'

# Login
curl -X POST http://localhost:3000/api/v1/api/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "admin@school.com",
    "password": "SecurePass123!"
  }'

# Response includes access_token and refresh_token

Health Check

# Full health check
curl http://localhost:3000/api/v1/health

# Readiness probe
curl http://localhost:3000/api/v1/health/ready

# Liveness probe
curl http://localhost:3000/api/v1/health/live

Using Swagger UI

For interactive API testing, visit:

Security Best Practices

Environment Variables

  • Never commit .env files to version control
  • Use .env.example as a template
  • Rotate JWT secrets regularly in production
  • Use strong, unique passwords for databases

Production Deployment

  • Enable HTTPS/TLS for all services
  • Use managed secrets (AWS Secrets Manager, Azure Key Vault, etc.)
  • Implement rate limiting on API Gateway
  • Enable Kafka authentication and encryption
  • Use read-only database replicas for read operations
  • Implement audit logging for sensitive operations

Database Security

  • Use least-privilege database users per service
  • Enable SSL for database connections
  • Regular backups with encryption
  • Implement row-level security where applicable

Contributing

Development Workflow

  1. Fork the repository and clone locally
  2. Create a feature branch: git checkout -b feature/your-feature-name
  3. Install dependencies: npm install
  4. Make your changes and test thoroughly
  5. Run linting: npm run lint
  6. Run tests: npm run test
  7. Commit with conventional commits:
    • feat: add new feature
    • fix: resolve bug
    • docs: update documentation
    • refactor: restructure code
  8. Push and create a Pull Request

Code Standards

  • Follow existing code style (ESLint + Prettier configured)
  • Write unit tests for new features
  • Update documentation for API changes
  • Keep commits atomic and well-described

Pull Request Guidelines

  • Provide clear description of changes
  • Reference related issues: Closes #123
  • Ensure CI checks pass
  • Request review from maintainers

CI/CD Pipeline

Continuous Integration

The project uses GitHub Actions for automated testing and validation:

  • Linting: ESLint checks on every commit
  • Testing: Jest unit and e2e tests
  • Build: TypeScript compilation validation
  • Prisma: Schema validation and migration checks

Continuous Deployment

  • Development: Auto-deploy to dev environment on main branch
  • Staging: Manual approval required
  • Production: Tagged releases only (v*.*.*)

Deployment Platforms

  • Render: Current hosting platform (see render.yaml)
  • Kubernetes: Production-ready manifests in k8s-deployment.yaml
  • Docker: Multi-stage Dockerfile for optimized builds

Monitoring & Observability

Health Monitoring

  • Health Endpoints: /health, /health/ready, /health/live
  • Kubernetes Probes: Configured in deployment manifests
  • Uptime Monitoring: Configure external monitoring (e.g., UptimeRobot)

Logging

  • Structured Logging: NestJS Logger with context
  • Log Levels: Configurable via environment variables
  • Production Logs: Centralized logging recommended (ELK, CloudWatch, etc.)
  • See LOGGING.md for implementation details

Metrics & Tracing

Recommended implementations:

  • Prometheus: Metrics collection
  • Grafana: Metrics visualization
  • Jaeger/Zipkin: Distributed tracing for microservices
  • Kafka Monitoring: Use Kafka UI (http://localhost:8080) in development

Error Tracking

  • Implement error tracking service (Sentry, Rollbar, etc.)
  • All exceptions are structured and logged
  • See EXCEPTION_HANDLING.md

Docker Deployment

Build Image

docker build -t sms-gateway:latest .

Run Container

docker run -p 3000:3000 \
  -e KAFKA_BROKERS="kafka1:9092,kafka2:9092,kafka3:9092" \
  -e JWT_ACCESS_SECRET="secret" \
  sms-gateway:latest

Kubernetes Deployment

kubectl apply -f k8s-deployment.yaml

Includes:

  • Deployment with 3 replicas
  • Health checks (liveness & readiness probes)
  • LoadBalancer service
  • Environment configuration

Documentation

Tech Stack

  • Framework: NestJS 11
  • Language: TypeScript 5.7
  • Message Broker: Apache Kafka (KRaft mode)
  • Database: PostgreSQL (via Prisma 6)
  • API Documentation: Swagger/OpenAPI
  • Validation: class-validator, class-transformer
  • Authentication: JWT, bcrypt
  • Testing: Jest
  • Containerization: Docker, Kubernetes

Scripts

npm run dev              # Start all services in development
npm run build            # Build production bundle
npm run start:prod       # Start production server
npm run lint             # Lint code
npm run format           # Format code with Prettier
npm run seed:all         # Seed all databases (auth, academics, teachers, students)
npm run seed:auth        # Seed auth database (users)
npm run seed:academics   # Seed academics database (school, classes, subjects)
npm run seed:teacher     # Seed teacher database
npm run seed:student     # Seed student database

Environment Variables

Variable Description Default
PORT Gateway HTTP port 3000
JWT_ACCESS_SECRET Access token secret -
JWT_REFRESH_SECRET Refresh token secret -
JWT_ACCESS_EXPIRE Access token expiry 15m
JWT_REFRESH_EXPIRE Refresh token expiry 7d
KAFKA_BROKERS Kafka broker addresses localhost:9094,...
*_DATABASE_URL Service database URLs -
DATABASE_URL_PUBLIC Public data database URL -
ADMIN_EMAIL Admin notification email admin@school.edu
FRONTEND_URL Frontend application URL http://localhost:4000

License

This project is licensed under the MIT License - see the LICENSE file for details.

Author

Sabin Shrestha (@masabinhok)

Support

For support, email sabin.shrestha.er@gmail.com or open an issue in the GitHub repository.


⭐ Star this repository if you find it helpful!

Made with ❤️ by Sabin Shrestha

About

NestJS microservices architecture for School Management System with Kafka messaging, role-based authentication, and Prisma ORM

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published