Back to Portfolio
MicroservicesFull-Stack5 Services

Learning
Management
System

A production-grade LMS built on a microservices architecture — five independently deployed services communicating through a Spring Cloud API Gateway with JWT authentication, Netflix Eureka service discovery, and Stripe-powered payments.

5
Services
30+
Endpoints
MySQL + PG
Databases
Stripe
Payments

Tech Stack

Spring BootSpring Cloud GatewayNetflix EurekaOpenFeignJWT / HS256Spring SecurityWebClient (Reactive)Node.jsExpressPrisma ORMMySQLPostgreSQLStripeAngular 17Axios

Architecture

Angular
:4200
API Gateway
:8080
Eureka
:8761
routes to
Auth Service
:8081
·
Course Service
:8082
·
Enrollment Service
:8083
Gateway validates JWT via reactive WebClient before forwarding any protected request to downstream services
Course Service resolves user identity via OpenFeign — Authorization header auto-forwarded by FeignConfig interceptor
All services register with Eureka on startup; Gateway routes via lb:// for automatic client-side load balancing

Services

Key Request Flows

1

Angular sends POST /auth/login via Gateway — public route, no AuthenticationFilter triggered.

2

Auth Service queries MySQL by email, compares credentials, calls JwtService.generateToken().

3

JWT generated with email · role · userId embedded — HS256 signed, 24 h expiry.

4

Token returned to Angular and attached as Bearer on every subsequent protected request.

Engineering Highlights

🔐
Token-propagated identity
JWT embeds userId and role — downstream services extract identity from the token rather than making secondary DB lookups, reducing latency and inter-service coupling.
Reactive gateway filter
AuthenticationFilter uses WebClient (non-blocking) instead of RestTemplate, keeping the Gateway fully reactive and able to handle high concurrency without thread starvation.
🔗
Transparent header forwarding
FeignConfig RequestInterceptor automatically propagates the Authorization header on every outbound Feign call — no manual header passing needed in any service method signature.
💳
Dual-confirm payment safety
Enrollments begin as PENDING. Stripe webhooks promote them to SUCCESS. A fallback /confirm-payment endpoint handles webhook delivery failures, preventing lost enrollments.
📦
Bulk course fetch
Enrollment Service calls POST /courses/by-ids instead of one HTTP request per enrolled course, collapsing N sequential calls into a single round-trip.
🗂
Polyglot persistence
Auth and Course services use MySQL with Spring Data JPA. Enrollment uses PostgreSQL with Prisma ORM and a pg connection pool adapter — each service optimised independently.

View Source

View on GitHub