This project demonstrates the Strangler Fig Pattern used to incrementally migrate functionality from a Legacy Monolith to a Modern Microservice architecture using Java 21 Virtual Threads.
The system consists of four main components:
- Discovery Server (Eureka): Service registry for dynamic lookups.
- API Gateway (Spring Cloud Gateway): The "Traffic Cop" that routes requests and implements Circuit Breakers.
- Legacy Monolith: The existing application handling
/api/users. - Modern Service: High-performance Java 21 service handling
/api/orders.
- Project Loom (Virtual Threads): The Modern Service is optimized for massive concurrency.
- Resilience: Integrated Resilience4j Circuit Breaker to prevent cascading failures.
- Dynamic Scaling: Automatic load balancing across multiple instances via Eureka.
- Zero-Downtime Migration: Path rewriting allows the frontend to stay consistent while the backend evolves.
In a stress test of 200 concurrent users (2,000 total requests):
- Modern (Java 21): ~1,267 req/sec | 99th% Latency: 400ms
- Legacy (Java 17): ~626 req/sec | 99th% Latency: 1,540ms
- JDK 21
- Maven 3.9+
- Docker (Optional)
- Start Discovery Server:
mvn spring-boot:runindiscovery-server - Start Legacy Monolith:
mvn spring-boot:runinlegacy-monolith - Start Gateway:
mvn spring-boot:runingateway-service - Start Modern Service:
mvn spring-boot:runinmodern-service
- Legacy Route:
GET http://localhost:8080/api/users/1 - Modern Route:
GET http://localhost:8080/api/orders/123 - Fallback Test: Stop the Modern Service and hit the order route to see the Circuit Breaker in action.
Run the full suite including context loads and routing tests:
mvn clean testTo make your repository look professional, ensure your folder structure looks like this:
strangler-fig-project/
├── .gitignore <-- (Include target/, .idea/, .DS_Store)
├── pom.xml <-- (The Parent POM)
├── README.md
├── discovery-server/
├── gateway-service/
├── legacy-monolith/
└── modern-service/
MIT