Overview
This is a fully-featured quiz application built using microservices architecture with Spring Boot 3.5.x and Spring Cloud 2025.0.0. It’s designed to demonstrate production-level distributed system patterns including service discovery, API gateway, circuit breakers, event-driven messaging, and distributed caching.
The project implements 10+ microservices that work together to provide quiz management, user authentication with social login, real-time notifications, analytics, and content delivery — all with proper resilience patterns to handle failure gracefully.
Architecture
The application follows a microservices architecture where each service has a single responsibility and communicates through well-defined APIs:
API Gateway (Port 8765) — Entry point with routing & resilience
↓
├── Auth Service (7999) — JWT/OAuth2 authentication
├── Quiz Service (8090) — Quiz operations
├── Question Service — Question bank management
├── API Content Service (8085) — Content delivery with Redis caching
├── Notification Service (7900) — Email via Kafka events
├── Analytics Service — Reporting & metrics
├── User Data Service — Profile management
└── Logging Service — Centralized logging
Infrastructure:
├── Consul (8500) — Service discovery & health checks
├── PostgreSQL — Primary data store
├── Redis — Distributed caching
└── Kafka — Event streaming
All services register with Consul for service discovery and expose health endpoints for monitoring.
Key Features
- Microservices Architecture — 10+ independent services with single responsibilities, each deployable separately
- Service Discovery — Dynamic service registration and discovery using HashiCorp Consul (migrated from Netflix Eureka)
- API Gateway — Spring Cloud Gateway with routing, load balancing, and resilience patterns using Resilience4j
- Authentication & Authorization — JWT-based auth with OAuth2 social login (Google & GitHub)
- Event-Driven Messaging — Asynchronous notifications using Apache Kafka for decoupled communication
- Distributed Caching — Redis integration for high-performance content delivery
- Resilience Patterns — Circuit breaker, retry, time limiter, and bulkhead for fault tolerance
- Inter-Service Communication — OpenFeign for declarative REST clients between microservices
- Health Monitoring — Spring Actuator endpoints with Prometheus metrics for observability
- Containerization — Docker support for all infrastructure components
Technical Highlights
Microservices Architecture with Spring Cloud
Each service is independently deployable and scalable:
Auth Service — Handles user authentication with JWT token generation and validates OAuth2 social logins. Uses PostgreSQL for user credentials and integrates with Google and GitHub OAuth2 providers.
Quiz & Question Services — Separate services for quiz management and question bank. Quiz service stores quiz metadata and references questions by ID, while Question service manages the question repository. This separation allows independent scaling based on usage patterns.
API Content Service — Implements Redis caching for frequently accessed content. Cache-aside pattern reduces database load and improves response times for read-heavy operations.
Notification Service — Listens to Kafka topics for events like quiz completion or score updates and sends email notifications asynchronously via Gmail SMTP.
Service Discovery with Consul
Services register themselves with Consul on startup and deregister on shutdown. Other services discover and communicate with each other through service names rather than hardcoded URLs:
@FeignClient(name = "question-service")
public interface QuestionClient {
@GetMapping("/questions/{id}")
Question getQuestionById(@PathVariable Long id);
}
Consul health checks monitor each service’s /actuator/health endpoint. Unhealthy services are automatically removed from the registry to prevent routing traffic to failing instances.
API Gateway with Resilience Patterns
The Spring Cloud Gateway serves as the single entry point and implements multiple resilience patterns using Resilience4j:
Circuit Breaker — Prevents cascading failures by opening the circuit after 50% failure rate over 10 requests. The gateway returns a fallback response instead of waiting for a failing service.
Retry — Automatically retries failed requests up to 3 times with a 2-second delay. Useful for transient network issues.
Time Limiter — Requests timeout after 2 seconds to prevent resource exhaustion from slow services.
Bulkhead — Limits concurrent calls to 5 to prevent thread pool exhaustion under high load.
These patterns ensure that one failing service doesn’t bring down the entire system.
Authentication & Security
JWT Authentication — The Auth Service generates signed JWT tokens containing user claims. The API Gateway validates these tokens for all protected routes before forwarding requests.
OAuth2 Social Login — Users can authenticate using their Google or GitHub accounts. The Auth Service exchanges OAuth2 authorization codes for user information and generates a JWT token for subsequent requests.
Token Validation — Every request through the API Gateway includes token validation. Invalid or expired tokens receive a 401 response without reaching backend services.
Event-Driven Architecture with Kafka
Services publish events to Kafka topics for asynchronous processing:
Quiz Completed Event → Kafka Topic → Notification Service → Email Sent
This decouples the quiz service from the notification service. If email sending fails, it doesn’t affect quiz submission. Kafka handles message persistence and retry logic.
Distributed Caching with Redis
The API Content Service uses Redis for caching frequently accessed content:
- Cache-Aside Pattern — Application checks cache first, falls back to database on miss, then updates cache
- TTL-based Expiration — Cached entries expire after a configured time to ensure freshness
- Reduced Database Load — Popular content is served from memory (sub-millisecond response times)
Database Architecture
Each service owns its database following the database-per-service pattern:
- Auth Service →
securitydb(user credentials, roles) - Quiz Service →
quizdb(quiz metadata, quiz-question associations) - Question Service →
questiondb(question bank with difficulty levels)
Schema migrations are managed through SQL scripts with proper indexing and constraints for data integrity.
Infrastructure & DevOps
Containerization with Docker
All infrastructure components run in Docker containers for consistent development and deployment:
Consul — Service registry and health monitoring Kafka — KRaft mode (no Zookeeper) for event streaming Redis — In-memory data store for caching PostgreSQL — Relational database with persistent volumes
Each container includes volume mounts for data persistence and proper networking for inter-container communication.
Observability
Health Checks — Every service exposes /actuator/health for monitoring
Prometheus Metrics — The API Gateway exposes metrics at /actuator/prometheus
Consul Dashboard — Real-time view of service health and registration status at http://localhost:8500
CORS Configuration
The API Gateway is configured to handle CORS for frontend applications running on:
- http://localhost:5173 (Vite)
- http://localhost:3000 (React)
Challenges & Learnings
Service discovery migration — Initially used Netflix Eureka for service discovery, but migrated to Consul for better health checking and integration with infrastructure orchestration. This required refactoring service configuration and updating inter-service communication logic.
Distributed transactions — Learned that traditional ACID transactions don’t work across microservices. Implemented eventual consistency patterns using event-driven architecture. For example, quiz completion triggers a Kafka event that the notification service consumes asynchronously.
Circuit breaker tuning — Finding the right circuit breaker thresholds required experimentation. Too sensitive causes unnecessary circuit opening, too lenient allows cascading failures. Settled on 50% failure rate over 10 requests as a good balance.
OAuth2 integration — Handling OAuth2 callback flows and token exchange required careful state management. Implemented proper redirect URIs and error handling for authorization failures.
Database schema design — Managing database schemas across multiple services required clear ownership boundaries. Used explicit SQL schema files with proper constraints and indexes rather than relying solely on Hibernate auto-generation.
Inter-service communication — Learned the importance of resilience patterns when services call each other. A slow question service could block quiz creation without timeouts and circuit breakers.
Technology Stack Deep Dive
Java 21 — Latest LTS with virtual threads and pattern matching Spring Boot 3.5.x — Production-ready framework with auto-configuration Spring Cloud 2025.0.0 — Distributed system patterns and integrations Consul — Service discovery with health checks OpenFeign — Declarative REST clients for inter-service calls Resilience4j — Fault tolerance library with circuit breaker, retry, bulkhead PostgreSQL — Robust ACID-compliant relational database Redis — High-performance in-memory data store Apache Kafka — Distributed event streaming platform Spring Security — Authentication and authorization framework JWT — Stateless token-based authentication OAuth2 — Social login integration Docker — Containerization for consistent environments Maven — Build automation and dependency management
Running the Project
The project includes comprehensive setup instructions covering:
- Prerequisites — Java 21, Maven, Docker
- Infrastructure Setup — Docker commands for Consul, Kafka, Redis, PostgreSQL
- Database Initialization — SQL scripts for schema creation
- Environment Variables — Configuration for OAuth2, JWT, and database credentials
- Service Startup — Recommended order for launching microservices
- Troubleshooting — Common issues and solutions
All services include Spring Actuator health endpoints and are monitored through Consul for operational visibility.
Roadmap
Currently working on:
- implementing monitoring and observability using Promethius and Graphana
- Front-end rework
- custom animations





