Production-style distributed system built with Java 21, Kotlin, Spring Boot 4, Kafka and PostgreSQL.
This project demonstrates practical implementation of:
- Domain-Driven Design (DDD)
- Saga Pattern (Orchestration)
- Outbox Pattern
- Idempotent Consumer
- Event-Driven Architecture
- Clean Architecture
The system consists of three microservices:
| Service | Language | Responsibility |
|---|---|---|
orders-service |
Java (Spring Boot 4) | Order lifecycle, Saga orchestration, Outbox publishing |
inventory-service |
Java (Spring Boot 4) | Stock management and reservation |
payments-service |
Kotlin (Spring Boot 3) | Payment processing |
Communication between services is fully asynchronous via Kafka.
Each service has its own database (Database per Service pattern).
POST /orders- Order created with status
INVENTORY_PENDING ReserveStockRequestedsaved to outbox- Inventory reserves stock → publishes
StockReserved - Orders service publishes
PaymentRequested - Payments service processes payment → publishes
PaymentSucceeded - Orders service marks order as
PAID
All cross-service communication happens through Kafka topics.
- Implemented in
orders-service saga_instancestable maintains state- Explicit state machine
- Idempotent event handling
- Each service has
outbox_messages - Events written in the same DB transaction as business state
- Background dispatcher publishes to Kafka
FOR UPDATE SKIP LOCKEDused for safe concurrent processing
processed_eventstable prevents double processing- Ensures safe retries and at-least-once delivery
- Aggregates encapsulate business logic
- Domain events emitted from aggregates
- Infrastructure maps Domain Events → Integration Events
- Clean separation:
domain
application
infrastructure
All integration events follow consistent structure:
{
"eventId": "uuid",
"eventType": "StockReserved",
"version": 1,
"occurredAt": "2026-02-11T10:49:43Z",
"data": { ... }
}This ensures:
- versioning
- schema stability
- consumer compatibility
Each service has its own PostgreSQL database.
Key tables:
orderssaga_instancesprocessed_eventsoutbox_messages
productsproduct_categorystock_itemsstock_reservationsstock_reservation_linesoutbox_messages
paymentsoutbox_messagesprocessed_events
Flyway is used for schema migrations.
- Docker
- Docker Compose
- Java 21+
- Gradle
docker-compose up --buildKafka, PostgreSQL and all services will start automatically.
curl -X POST http://localhost:8081/orders \
-H "Content-Type: application/json" \
-d '{
"customerId": "CUST-1",
"items": [
{ "sku": "TV-LG-65-OLED", "quantity": 1 },
{ "sku": "DISHWASHER-SIEMENS", "quantity": 1 }
]
}'GET http://localhost:8081/orders/{orderId}Swagger UI available:
- Orders:
http://localhost:8081/swagger-ui.html - Inventory:
http://localhost:8083/swagger-ui.html - Payments:
http://localhost:8082/swagger-ui.html
- Spring Boot 4 (Java 21)
- Kotlin Spring Boot
- Kafka (event-driven architecture)
- PostgreSQL + Flyway
- Hibernate + JPA
- Structured logging
- Clean Architecture layering
- Explicit state transitions
- No anemic domain model
- Explicit integration event mapping
CREATED
INVENTORY_PENDING
PAYMENT_PENDING
PAID
PAYMENT_FAILED
CANCELLED
INVENTORY_REQUESTED
INVENTORY_RESERVED
PAYMENT_REQUESTED
PAID
PAYMENT_FAILED
CANCELLED
- Orchestration Saga instead of Choreography → clearer flow control
- Explicit envelope events for versioning
- Domain Events ≠ Integration Events
- Outbox for guaranteed delivery
- Idempotency at consumer side
- No synchronous inter-service calls
The goal was to build a realistic production-style distributed system, demonstrating:
- handling of distributed transactions
- event-driven architecture
- reliability patterns
- domain modeling discipline
- clean infrastructure boundaries
This project is intended as a portfolio-grade example of building resilient microservices using modern JVM stack.
- Inventory step compensation
- Dead-letter topics
- Observability (Prometheus + Grafana)
- OpenTelemetry tracing
- Contract testing
- Kubernetes deployment manifests