saga-full — system architecture

Six independent services. No central saga orchestrator.

api-gateway-service is the only synchronous entry point a client ever talks to — one gRPC hop to user-service for auth, one guarded HTTP route into the Kafka-driven saga chain. Everything past that gateway reacts to events independently; nothing issues commands down the chain. See Saga Flow for how a single order actually moves through it.

Entry Points

Client
↓ HTTPS
api-gateway-service (WebFlux, :8080)
↓ gRPC user-service (:9090) POST /auth/login → Login RPC
↓ HTTP, JwtPerimeterGuard order-service (:8081) POST /orders → saga entry point
↓ order-created-topic
payment-service → restaurant-service
↑↓ restaurant-approved / restaurant-rejected-topic, back to order-service + payment-service

Modules

Entry point

api-gateway-service

  • Reactive WebFlux + Spring Cloud Gateway
  • JWT perimeter guard, local HMAC verification
  • Resilience4j circuit breaker on the downstream hop
gRPC only

user-service

  • Login + JWT issuance
  • No HTTP surface at all
  • BCrypt via spring-security-crypto
Contract

user-contract

  • One hand-written user.proto
  • Everything else protoc-generated
Saga entry

order-service

  • Owns the order's PENDING → SUCCESS/CANCELLED lifecycle
  • Transactional outbox → Kafka
Choreography

payment-service

  • Charges on order creation
  • Compensates (refunds) on rejection
Choreography

restaurant-service

  • Inventory allocation, ticket creation
  • The saga's approve/reject decision
i

Every Kafka-driven service follows the same transactional-outbox shape (domain write + outbox row, one transaction, then a separate poller). What's actually different per service — ports, topics, schemas — is on the Services Reference diagram. Testing follows its own layered approach, independent of this module split — see the Testing Strategy diagram.