Learn by example: Production-ready microservices with Spring Boot 3.x, Java 21, and Domain-Driven Design. Master modern architecture patterns through real-world code.
# Clone and start all services
docker-compose up
# Access services
- Gateway: http://localhost:8081
- User Service: http://localhost:8080/swagger-ui.html
- Bookstore Service: http://localhost:8082/swagger-ui.html
- Grafana: http://localhost:3000Architecture Patterns:
- Microservices decomposition with clear boundaries
- Domain-Driven Design (value objects, aggregates, bounded contexts)
- API Gateway with reactive programming
- Database per service with multi-tenancy
Modern Java & Spring:
- Java 21 features (records, pattern matching, text blocks)
- Spring Boot 3.x with WebFlux reactive programming
- Type-safe configuration and validation
Production Readiness:
- JWT authentication with RSA256
- Distributed rate limiting and circuit breakers
- Observability (metrics, tracing, structured logging)
- Multi-tenant data isolation
┌─────────────┐
│ Clients │
└──────┬──────┘
│
▼
┌─────────────────────────────────────┐
│ 🌐 Gateway (Port 8081) │
│ • JWT Validation │
│ • Rate Limiting (Redis) │
│ • Circuit Breaker │
│ • Request Routing │
└──────┬──────────────────┬───────────┘
│ │
▼ ▼
┌──────────────┐ ┌──────────────────┐
│ 🔐 User │ │ 📚 Bookstore │
│ Service │ │ Service │
│ (Port 8080) │ │ (Port 8082) │
│ │ │ │
│ • Auth/JWT │ │ • DDD Patterns │
│ • Multi- │ │ • Value Objects │
│ Tenancy │ │ • Aggregates │
└──────┬───────┘ └──────┬───────────┘
│ │
▼ ▼
PostgreSQL PostgreSQL
(Schema-per- (Books &
Tenant) Inventory)
Key Decisions:
- Database Per Service - Independent data ownership and scaling
- Reactive Gateway - Non-blocking I/O for high throughput
- Schema-Per-Tenant - Strong data isolation for multi-tenancy
- JWT Context Propagation - Stateless authentication across services
Learn: Value objects, aggregates, domain services, bounded contexts
DDD Patterns:
// Value Objects - Self-validating, immutable
var isbn = ISBN.of("978-0-13-468599-1");
var price = Money.usd(new BigDecimal("29.99"));
// Aggregate Root - Business logic in domain
var book = Book.create(title, author, isbn, price, description, category);
boolean canSell = book.canBeSold(); // Combines availability + stock
// Domain Service - Cross-aggregate operations
duplicateIsbnChecker.ensureUnique(isbn);Bounded Contexts:
catalog- Book managementinventory- Stock tracking and reservationsshared- Common value objects (ISBN, Money, BookId)
Learn: JWT lifecycle, token blacklisting, schema-per-tenant isolation
Security Patterns:
- JWT with RSA256 (access: 15min, refresh: 7 days)
- JTI-based blacklisting with Redis TTL
- Account lockout (5 attempts → 15min)
- Email verification with rate limiting (3/hour)
- Schema-per-tenant data isolation
Multi-Tenancy:
// Each tenant gets separate PostgreSQL schema
TenantContext.executeInTenantContext(tenantId, () ->
userRepository.countByEnabledTrue()
);Learn: Reactive programming, distributed rate limiting, circuit breakers
Reactive Patterns:
// Non-blocking filter chain
public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
return validateToken(exchange)
.flatMap((userContext) -> enrichHeaders(exchange, userContext))
.then(chain.filter(exchange));
}Features:
- Sliding window rate limiting (Redis ZSET)
- Circuit breaker per service (Resilience4j)
- JWT validation with
ReactiveSecurityContextHolder - Correlation ID generation and propagation
| Layer | Technology |
|---|---|
| Runtime | Java 21 (records, pattern matching, text blocks) |
| Framework | Spring Boot 3.5.6, Spring Cloud 2025.0.0 |
| Database | PostgreSQL 15+ with Liquibase migrations |
| Caching | Redis (distributed cache, rate limiting, token blacklist) |
| Security | JWT RSA256, Spring Security OAuth2 Resource Server |
| Resilience | Resilience4j (circuit breaker, rate limiter) |
| Observability | OpenTelemetry, Prometheus, Grafana, Loki |
| API Docs | SpringDoc OpenAPI 3 with Swagger UI |
| Testing | JUnit 5, Testcontainers, ArchUnit, Reactor Test |
| Containers | Docker with multi-stage builds, Docker Compose |
Value Objects:
@Embeddable
public class ISBN {
private String value;
public static ISBN of(String value) {
// Validation logic
return new ISBN(normalize(value));
}
}Aggregate Roots:
@Entity
public class Book extends AggregateRoot<Long> {
private ISBN isbn;
private Money price;
public boolean canBeSold() {
return this.available && isInStock();
}
}Database Per Service:
- User Service → PostgreSQL (users, roles, tenants)
- Bookstore Service → PostgreSQL (books, inventory)
- No shared databases or cross-service joins
JWT Context Propagation:
Authorization: Bearer <jwt-token>
X-User-ID: 123
X-Username: john.doe
X-User-Roles: USER,ADMIN
X-Tenant-ID: tenant-123
X-Correlation-ID: abc-123
Circuit Breaker:
resilience4j:
circuitbreaker:
instances:
bookstore-service:
failure-rate-threshold: 50
wait-duration-in-open-state: 10sJWT Authentication:
- RSA256 signing with JWK Set endpoint
- Token validation at gateway and services
- Comprehensive claims (userId, roles, permissions, tenantId)
Token Blacklisting:
// Redis-backed logout with TTL
redisTemplate.opsForValue().set(
"blacklist:" + jti,
"true",
Duration.ofMinutes(15)
);Role-Based Access Control:
@PreAuthorize("hasAnyRole('ADMIN', 'SUPER_ADMIN')")
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteBook(@PathVariable Long id) {
bookService.deleteBook(id);
return ResponseEntity.noContent().build();
}Non-Blocking I/O:
// WebFlux with Mono/Flux
public Mono<ServerResponse> handleRequest(ServerRequest request) {
return userService
.findById(id)
.flatMap((user) -> ServerResponse.ok().bodyValue(user))
.switchIfEmpty(ServerResponse.notFound().build());
}Reactive Rate Limiting:
// Sliding window with Redis ZSET
return redisTemplate.opsForZSet()
.removeRangeByScore(key, 0, cutoffTime)
.then(redisTemplate.opsForZSet().add(key, requestId, currentTime))
.flatMap(added -> redisTemplate.opsForZSet().count(key, windowStart, currentTime))
.map(count -> count <= limit);- Study value objects (
ISBN,Money) - Understand aggregates (
Book,Inventory) - Explore bounded contexts (
catalog,inventory) - Learn factory methods and domain services
Why first: DDD provides the foundation for maintainable domain logic.
- Understand JWT generation and validation
- Study schema-per-tenant isolation
- Explore token blacklisting and account protection
- Learn audit logging patterns
Why second: Security is critical and builds on domain concepts.
- Understand reactive programming with WebFlux
- Study distributed rate limiting with Redis
- Explore circuit breaker patterns
- Learn request transformation and routing
Why third: Gateway ties everything together with advanced patterns.
- Trace requests: client → gateway → services
- Understand correlation ID propagation
- Study JWT context flow across services
- Learn distributed tracing with OpenTelemetry
Why last: Integration shows how all patterns work together.
Exercise 1: Add a New Value Object
- Create
Publishervalue object in Bookstore Service - Add validation (name, country, founded year)
- Update
Bookaggregate to include publisher - Write unit tests for validation logic
Exercise 2: Implement a New Endpoint
- Add "Get Books by Publisher" endpoint
- Implement repository query method
- Add Redis caching
- Write integration tests with Testcontainers
Exercise 3: Add Custom JWT Claims
- Extend User Service to include department in JWT
- Update Gateway to propagate department header
- Modify Bookstore Service to log department context
- Test end-to-end claim propagation
Exercise 4: Create a New Microservice
- Build Order Service following established patterns
- Implement order placement with book reservation
- Add JWT validation and user context extraction
- Register routes in Gateway Service
// Current: Book aggregate
Book book = Book.create(title, author, isbn, price, description, category);
// Adapt to: Product catalog
Product product = Product.create(name, sku, price, description, category);
// Adapt to: Asset management
Asset asset = Asset.create(name, serialNumber, cost, location, department);Maintain these principles:
- Value objects for domain concepts
- Aggregate roots with business logic
- Factory methods for creation
- Bounded contexts for organization
E-Commerce:
- User Service → Customer authentication
- Bookstore → Product catalog
- Add: Order Service, Shipping Service
Healthcare:
- User Service → Provider/patient auth
- Bookstore → Medical records
- Add: Appointment Service, Billing Service
Financial:
- User Service → Customer identity/KYC
- Bookstore → Financial products
- Add: Transaction Service, Reporting Service
Once services are running:
- User Service: http://localhost:8080/swagger-ui.html
- Gateway Service: http://localhost:8081/swagger-ui.html
- Bookstore Service: http://localhost:8082/swagger-ui.html
Monitoring:
- Prometheus: http://localhost:9090
- Grafana: http://localhost:3000
- Health Checks: http://localhost:808x/actuator/health
Official Documentation:
Recommended Books:
- "Domain-Driven Design" by Eric Evans
- "Building Microservices" by Sam Newman
- "Reactive Spring" by Josh Long
- "Spring Boot: Up and Running" by Mark Heckler
Community:
This platform is your blueprint for building production-ready microservices. The code demonstrates real-world patterns you can learn from and adapt to your own projects.