Gateway / Orders
The request enters through one controlled edge.
The gateway validates a PS256-signed JWT, adds a request ID and forwards the order. The Orders Service validates and persists it before emitting an event.
Case study 01 · Event-driven backend
A finance-style backend built to make service boundaries, event flow and state ownership visible.
01 / Problem
I wanted to model a backend closer to the systems used in financial technology: independent services, asynchronous events, durable state and explicit failure paths.
The design needed to show how an order enters at the edge, becomes a trade, reaches an immutable transaction journal and updates a portfolio read model—without hiding the hard parts behind one database transaction.
How do you keep one business event coherent while it crosses multiple services and storage boundaries?
02 / Architecture
Spring Cloud Gateway owns edge authentication, tracing headers, rate limiting and circuit breakers. Orders publish to Redpanda; matching emits each trade to three independent consumers, and only the transaction processor’s recorded event feeds the portfolio projection.
03 / Walkthrough
Gateway / Orders
The gateway validates a PS256-signed JWT, adds a request ID and forwards the order. The Orders Service validates and persists it before emitting an event.
Redpanda / Kafka
order.placed.v1 decouples the request path from downstream processing. Consumers can progress independently and handle redelivery explicitly.
Matching Engine
The matching engine maintains its book, records processed event IDs for idempotency and emits trade.executed.v1 when compatible orders cross.
Transactions / Portfolio
The transaction processor journals the trade. A downstream event updates portfolio positions and realized P&L without making the gateway own financial state.
04 / Decisions
Order and trade flows naturally fan out. Kafka keeps downstream consumers independent and makes new projections possible.
Durable financial state stays in relational storage; Redis is reserved for fast operational concerns such as rate limits and market-data cache.
Consumer ledgers and duplicate-aware handlers acknowledge that at-least-once delivery can repeat a message.
Docker Compose proves service boundaries and integration locally before deployment orchestration adds another layer of complexity.
05 / Evidence
06 / Reflection
The next meaningful layer is observability: OpenTelemetry traces across the order path, Kafka lag dashboards, structured logs and actionable dead-letter alerts. Schema governance and an outbox pattern would tighten the event boundaries further.