Back to PortfolioLearning
··
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