All projectsDistributed systems

Order-Saga.

Spring Boot 3.4KafkaPostgreSQLSpring CloudDocker
01

What it does

Order-processing system across 5 microservices (order, inventory, payment, shipping, notification) using the Choreography Saga pattern — no central orchestrator, services coordinate purely through Kafka events, with automatic compensation logic if a step fails (e.g. releasing reserved stock on payment failure). Spring Boot 3.4.3, Java 17, Kafka, PostgreSQL, Spring Cloud (Eureka, Gateway, OpenFeign), Docker Compose.

02

How it works

A request enters through Spring Cloud Gateway and reaches the order service, which writes the order and publishes its own event. From that point nothing coordinates the flow centrally: each service reacts to an event and publishes its own result event.

Inventory reserves stock and publishes the outcome. Payment reacts to the reservation, calls a mock payment provider through OpenFeign, and publishes success or failure. Shipping reacts to a successful payment, and notification reacts to whatever the saga ends on.

When a step fails, the compensation path runs on the same event bus. A payment failure releases the reserved stock and fails the order; an inventory failure fails the order and notifies. The order's status chip moves through PENDING, INVENTORY_RESERVED, PAYMENT_PROCESSING, COMPLETED, FAILED, and COMPENSATING.

Because Kafka delivers at least once, every service records processed event IDs in a ProcessedEvent table and ignores repeats, and the Product entity uses an @Version field so two concurrent reservations cannot double-book the same stock.

03

Design decisions

  1. 01Choreography, not orchestration: each service reacts to events and publishes its own result event; nothing coordinates centrally.
  2. 02Idempotent consumers: every service records processed event IDs in a ProcessedEvent table to tolerate Kafka's at-least-once delivery.
  3. 03Optimistic locking with @Version on the Product entity prevents double-booking inventory under concurrency.
  4. 04Compensation: a payment failure automatically releases reserved stock and fails the order; an inventory failure fails the order and notifies.
  5. 05One PostgreSQL database per service; OpenFeign clients call mock payment, shipping, and email providers that can be switched to fail for testing.
  6. 06Observability through the Eureka dashboard and Kafka UI; order status lifecycle PENDING, INVENTORY_RESERVED, PAYMENT_PROCESSING, COMPLETED, FAILED, COMPENSATING.
04

Stack

Language
Java 17
Framework
Spring Boot 3.4.3, Spring Data JPA
Service discovery
Spring Cloud Eureka, Spring Cloud 2024.0.1
Edge
Spring Cloud Gateway
Service-to-service
Spring Cloud OpenFeign
Messaging
Apache Kafka 7.5.0, Zookeeper, Kafka UI
Storage
PostgreSQL 15 (one per service)
Build and run
Maven, Docker, Docker Compose
05

Source

More work

See the other systems, or say hello.