Back to selected work

Case study 01 · Event-driven backend

TradeStream

A finance-style backend built to make service boundaries, event flow and state ownership visible.

Role
Designer & developer
Stack
Java, Spring Boot, Kafka, PostgreSQL, Redis
Type
Independent systems project
Status
Working local stack

More than another CRUD app.

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.

Design question

How do you keep one business event coherent while it crosses multiple services and storage boundaries?

A visible path from request to position.

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.

TradeStream order flow: Orders publishes to Matching; each executed trade independently updates Orders, Market Data and Transactions; recorded transactions then update Portfolio
Implemented event flowRequest → trade fan-out → position

Follow one order through the system.

Step 1 of 4

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.

The choices that shape the system.

D / 01

Events over chained REST

Order and trade flows naturally fan out. Kafka keeps downstream consumers independent and makes new projections possible.

D / 02

PostgreSQL owns truth

Durable financial state stays in relational storage; Redis is reserved for fast operational concerns such as rate limits and market-data cache.

D / 03

Idempotency is designed in

Consumer ledgers and duplicate-aware handlers acknowledge that at-least-once delivery can repeat a message.

D / 04

Compose before Kubernetes

Docker Compose proves service boundaries and integration locally before deployment orchestration adds another layer of complexity.

Built to be interrogated.

7domain and edge services in the local stack
PS256asymmetric JWT validation at the gateway
E2Escripted trade, cancel, restart and dead-letter flows
  • GitHub Actions builds the gateway, starts the Compose stack and waits for service health before testing.
  • Flyway manages schemas; Actuator exposes service health and metrics.
  • Known dual-write and cancellation-race risks are documented rather than described as solved.

What I would build next.

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.

  • Add Prometheus, Grafana, Loki and distributed tracing.
  • Introduce schema contracts and compatibility checks in CI.
  • Replace remaining dual writes with an outbox-based publishing path.