A comprehensive microservices-based application for booking flights, managing users, and sending notifications. This system is built using modern technologies with a focus on scalability, observability, and maintainability.
flights.mp4
- Architecture
- Tech Stack
- Database Design
- Services Overview
- Monitoring & Observability
- Getting Started
- API Documentation
- Deployment
The system follows a microservices architecture pattern with the following components:
βββββββββββββββ
β Frontend β (Next.js - Port 3000)
β (Next.js) β
ββββββββ¬βββββββ
β
βΌ
βββββββββββββββββββ
β API Gateway β (Port 5000)
β (Express.js) β
βββββββ¬ββββββββ¬ββββ
β β
βΌ βΌ
ββββββββββββ ββββββββββββββββββββ
β Flights β β Booking Service β
β Service β β (Port 4000) β
β(Port 3500)β βββββββββββ¬βββββββββ
ββββββββββββ β
βΌ
βββββββββββββββββββ
β Notification β
β Service β
β (Port 8000) β
βββββββββββββββββββ
- Synchronous: REST APIs via API Gateway
- Asynchronous: Redis Queue (BullMQ) for email notifications
- Service Discovery: Environment-based configuration
- Authentication: JWT-based authentication via API Gateway
| Component | Technology | Version | Purpose |
|---|---|---|---|
| Runtime | Node.js | v18+ | JavaScript runtime |
| Framework | Express.js | v5.x | Web framework |
| Language | TypeScript | v5.x | Type-safe JavaScript |
| ORM | Prisma | v7.x | Database ORM |
| Database | MySQL | Latest | Primary database |
| Cache/Queue | Redis | Latest | Message queue & caching |
| Authentication | JWT (jsonwebtoken) | v9.x | Token-based auth |
| Validation | Zod | v3.x | Schema validation |
| Logging | Winston | v3.x | Structured logging |
| Monitoring | Prometheus | Latest | Metrics collection |
| Visualization | Grafana | Latest | Metrics visualization |
| Component | Technology | Version |
|---|---|---|
| Framework | Next.js | 16.1.1 |
| UI Library | React | 19.2.3 |
| Styling | Tailwind CSS | v4 |
| HTTP Client | Axios | v1.13.2 |
| UI Components | Radix UI | Latest |
| Component | Technology | Purpose |
|---|---|---|
| Containerization | Docker | Service containerization |
| Orchestration | Docker Compose | Local development |
| Metrics | Prometheus | Metrics scraping |
| Dashboards | Grafana | Metrics visualization |
| Queue Management | Bull Board | Queue monitoring UI |
- bcryptjs: Password hashing
- express-rate-limit: Rate limiting
- http-proxy-middleware: API Gateway proxying
- bullmq: Redis-based job queue
- nodemailer: Email sending
- handlebars: Email templating
- prom-client: Prometheus metrics client
- winston-daily-rotate-file: Log rotation
The system uses MySQL as the primary database with three separate databases:
flights_booking- Flights Service (Inventory Management)flights_dev- Booking Service (Bookings & Payments)api_gateway_db- API Gateway (Users & Authentication)
Cities (1) ββ< (Many) Airport (1) ββ< (Many) Flight
β
βββ< (Many) Flight (Arrival)
Airplane (1) ββ< (Many) Flight
Airplane (1) ββ< (Many) Seat
Entity Relationships:
-
Cities β Airport (One-to-Many)
- One city can have multiple airports
Airport.cityIdβCities.id(CASCADE on delete/update)
-
Airport β Flight (One-to-Many for Departures)
- One airport can have multiple departing flights
Flight.departureAirportIdβAirport.code(CASCADE on delete)
-
Airport β Flight (One-to-Many for Arrivals)
- One airport can have multiple arriving flights
Flight.arrivalAirportIdβAirport.code(CASCADE on delete)
-
Airplane β Flight (One-to-Many)
- One airplane can be used in multiple flights
Flight.airplaneIdβAirplane.id(CASCADE on delete)
-
Airplane β Seat (One-to-Many)
- One airplane has multiple seats
Seat.airplaneIdβAirplane.id(CASCADE on delete)
Tables:
| Table | Key Fields | Relationships |
|---|---|---|
Cities |
id, city (unique) |
β Airport |
Airport |
id, code (unique), name, cityId |
β Cities, β Flight (departure/arrival) |
Airplane |
id, modelNumber (unique), capacity |
β Flight, β Seat |
Flight |
id, flightNumber (unique), airplaneId, departureAirportId, arrivalAirportId, totalSeats, price |
β Airplane, β Airport (2x) |
Seat |
id, airplaneId, row, col, type (enum) |
β Airplane |
user |
id, email (unique), name |
- |
Enums:
SeatType:BUSINESS,ECONOMY,PREMIUM_ECONOMY,FIRST_CLASS
User (External) ββ< (Many) Bookings
Flight (External) ββ< (Many) Bookings
Entity Relationships:
- Bookings references external
userIdandflightId - No foreign key constraints (service boundary)
Tables:
| Table | Key Fields | Relationships |
|---|---|---|
Bookings |
id, flightId, userId, status (enum), noOfSeats, totalCost |
References external services |
Enums:
BookingStatus:BOOKED,CANCELLED,INITIATED,PENDING
User (1) ββ< (Many) UserRole (Many) ββ> (1) Role
Entity Relationships:
-
User β UserRole (One-to-Many)
- One user can have multiple roles
UserRole.userIdβUser.id(CASCADE on delete)
-
Role β UserRole (One-to-Many)
- One role can be assigned to multiple users
UserRole.roleIdβRole.id(CASCADE on delete)
-
UserRole is a junction table with unique constraint on
[userId, roleId]
Tables:
| Table | Key Fields | Relationships |
|---|---|---|
User |
id, email (unique), name, password |
β UserRole |
Role |
id, name (enum, unique) |
β UserRole |
User_Roles |
id, userId, roleId |
β User, β Role |
Enums:
ROLE:ADMIN,CUSTOMER,FLIGHT_COMPANY
# Flights Service
DATABASE_URL="mysql://root:password@localhost:3306/flights_booking"
# Booking Service
DATABASE_URL="mysql://root:password@localhost:3306/flights_dev"
# API Gateway
DATABASE_URL="mysql://root:password@localhost:3306/api_gateway_db"Purpose: Single entry point for all client requests
Responsibilities:
- User authentication and authorization (JWT)
- Request routing and proxying to microservices
- Rate limiting
- Request validation
Key Features:
- JWT token generation and validation
- Role-based access control (RBAC)
- Proxy middleware for service routing
- Express rate limiting
Database: api_gateway_db
Purpose: Manages flight inventory and related entities
Responsibilities:
- CRUD operations for flights, airplanes, airports, cities
- Flight search and filtering
- Seat inventory management
- Prometheus metrics collection
Key Features:
- Advanced flight search with filters (price, date, routes)
- Real-time seat availability tracking
- Prometheus metrics endpoint (
/metrics) - Comprehensive logging with Winston
Database: flights_booking
Monitoring Port: 3500 (metrics endpoint)
Purpose: Handles booking lifecycle and payments
Responsibilities:
- Booking creation and management
- Payment processing
- Seat reservation coordination with Flights Service
- Email notification queue producer
- Prometheus metrics collection
- Cron jobs for expired booking cleanup
Key Features:
- Booking state management (INITIATED β BOOKED/CANCELLED)
- Idempotent payment processing
- Automatic cancellation of expired bookings (10-15 mins)
- Bull Board UI for queue monitoring (
/ui) - Prometheus metrics endpoint (
/metrics)
Database: flights_dev
Monitoring Port: 4000 (metrics endpoint)
Purpose: Asynchronous email notification worker
Responsibilities:
- Consuming email jobs from Redis queue
- Rendering email templates (Handlebars)
- Sending emails via Nodemailer
Key Features:
- BullMQ worker for queue processing
- Template-based email rendering
- Retry mechanism for failed emails
- Scalable worker architecture
No Database (stateless worker)
Purpose: User-facing web application
Technology: Next.js 16 with React 19
Features:
- Flight search interface
- Booking management
- User authentication UI
The system includes comprehensive monitoring for Flights Service and Booking Service using Prometheus and Grafana.
Location: ./prometheus.yml
global:
scrape_interval: 2s
scrape_configs:
- job_name: "flight-service"
static_configs:
- targets: ["192.168.1.187:3500"]
- job_name: "booking-service"
static_configs:
- targets: ["192.168.1.187:4000"]
Access: http://localhost:9090
Access: http://localhost:3010 (default credentials: admin/admin)
Data Source: Prometheus at http://localhost:9090 (or http://prom-server:9090 if running in Docker network)
Both services expose metrics at /metrics:
- Flights Service:
http://localhost:3500/metrics - Booking Service:
http://localhost:4000/metrics
| Metric Name | Type | Description | Labels |
|---|---|---|---|
http_requests_total |
Counter | Total HTTP requests | method, route, status_code |
http_request_duration_ms |
Histogram | Request duration in milliseconds | method, route, status_code |
active_requests |
Gauge | Currently active requests | - |
flight_search_total |
Counter | Total flight searches | has_price, has_date, has_trips |
flight_search_results_count |
Histogram | Number of results per search | - |
process_* |
Gauge | Node.js process metrics (CPU, memory, etc.) | - |
| Metric Name | Type | Description | Labels |
|---|---|---|---|
http_requests_total_booking |
Counter | Total HTTP requests | method, route, status_code |
http_request_duration_seconds_booking |
Histogram | Request duration in seconds | method, route, status_code |
active_requests_booking |
Gauge | Currently active requests | - |
booking_attempts_total |
Counter | Total booking attempts | - |
booking_success_total |
Counter | Total successful bookings | - |
booking_failed_total |
Counter | Total failed bookings | reason |
booking_reservation_expired_total |
Counter | Expired reservations | - |
process_* |
Gauge | Node.js process metrics | - |
# Start Prometheus (Grafana needs to be set up separately or added to docker-compose)
docker-compose up
# Access Prometheus
open http://localhost:9090
# Note: Grafana should be installed separately or added to docker-compose.yml
# Access Grafana (if configured)
open http://localhost:3010- Node.js (v18 or higher)
- MySQL (v8.0 or higher)
- Redis (v6.0 or higher)
- Docker & Docker Compose (for monitoring stack)
- npm or yarn
- Clone the repository
git clone <repository-url>
cd flights- Install dependencies for each service
# API Gateway
cd "api gateway" && npm install && cd ..
# Flights Service
cd "flights service" && npm install && cd ..
# Booking Service
cd "flights booking service" && npm install && cd ..
# Notification Service
cd "notification service" && npm install && cd ..
# Frontend
cd frontend && npm install && cd ..- Set up databases
Create three MySQL databases:
CREATE DATABASE flights_booking;
CREATE DATABASE flights_dev;
CREATE DATABASE api_gateway_db;- Configure environment variables
Create .env files in each service directory (see individual service READMEs for details).
- Run Prisma migrations
# Flights Service
cd "flights service"
npx prisma migrate dev
npx prisma generate
# Booking Service
cd "../flights booking service"
npx prisma migrate dev
npx prisma generate
# API Gateway
cd "../api gateway"
npx prisma migrate dev
npx prisma generateOption 1: Manual (Development)
Open 5 separate terminals:
# Terminal 1: Flights Service
cd "flights service" && npm run dev
# Terminal 2: Booking Service
cd "flights booking service" && npm run dev
# Terminal 3: Notification Service
cd "notification service" && npm run dev
# Terminal 4: API Gateway
cd "api gateway" && npm run dev
# Terminal 5: Frontend
cd frontend && npm run devOption 2: Docker Compose (Monitoring Stack)
# Start Prometheus and Grafana
docker-compose up
docker run -d -p 3010:3000 --name=grafana grafana/grafana-oss| Service | Port | Health Check |
|---|---|---|
| API Gateway | 5000 | http://localhost:5000/api/v1/ping |
| Flights Service | 3500 | http://localhost:3500/api/v1/ping |
| Booking Service | 4000 | http://localhost:4000/api/v1/ping |
| Notification Service | 8000 | http://localhost:8000/api/v1/ping |
| Frontend | 3000 | http://localhost:3000 |
| Prometheus | 9090 | http://localhost:9090 |
| Grafana | 3010 | http://localhost:3010 (if configured) |
See API_DOC.md for detailed API documentation.
Base URL: http://localhost:5000 (via API Gateway)
| Method | Endpoint | Description | Auth |
|---|---|---|---|
POST |
/api/v1/signup |
Register user | β |
POST |
/api/v1/signin |
Login | β |
GET |
/flightsService/api/v1/flight |
Search flights | β |
POST |
/flightsService/api/v1/flight |
Create flight | β (Admin) |
POST |
/bookingService/api/v1/booking |
Create booking | β |
POST |
/bookingService/api/v1/booking/payments |
Process payment | β |
Each service requires specific environment variables. See individual service READMEs:
- Database: Use managed MySQL (RDS, Cloud SQL, etc.)
- Redis: Use managed Redis (ElastiCache, Cloud Memorystore, etc.)
- Monitoring: Configure Prometheus for production scraping
- Logging: Set up centralized logging (ELK, CloudWatch, etc.)
- Security:
- Use strong JWT secrets
- Enable HTTPS/TLS
- Configure CORS properly
- Set up rate limiting
- Scaling: Services are stateless and can be horizontally scaled
- Health Checks: Implement proper health check endpoints for load balancers