Event-driven trading system with Spring/Java microservices, Kafka/Redpanda, PostgreSQL, Redis, and Docker. This root README is the entry for recruiters and engineers: what’s here today, how to run it, and where to look next.
- Edge security: Spring Cloud API Gateway (Java 21) validates PS256 JWT at the perimeter, injects
X-Request-Id, applies Resilience4j circuit breakers, and Redis IP rate limits login. - Order → Trade pipeline: Orders Service → Matching Engine (price–time priority) → Transaction Processor (immutable journal).
- Read models: Portfolio Service projects positions & realized PnL. Market Data Consumer aggregates OHLCV and keeps “latest” hot in Redis.
- Everything is containerized; Flyway manages schemas; Actuator provides health/metrics.
This repo is educational/portfolio—it simulates a trading stack; it does not process real money.
TradeStream is my strongest Java/Spring Boot backend and fintech systems project. I built it to model how order, trade, transaction and portfolio flows can move through separate services without becoming a single CRUD app.
- Problem: build a finance-style backend where service boundaries, state ownership and event flow are visible.
- Build: Spring Cloud Gateway handles edge concerns; auth and user services manage access; orders publish events to Redpanda/Kafka; the matching engine emits trade events; transaction and portfolio services project downstream state into PostgreSQL-backed models.
- Evidence: the repo includes Docker Compose orchestration, GitHub Actions CI, end-to-end scripts, architecture docs, event contracts, security notes and operational runbooks.
- Main lesson: event-driven systems need clear ownership of durable state, idempotency, retries, observability and honest boundaries between what is working locally and what would be needed for production.
| Component | Path | Status | Notes |
|---|---|---|---|
| API Gateway | api-gateway/ |
✅ | PS256 JWT verification, Redis rate limit (login), circuit breakers, CORS, tracing header |
| User Registration | services/user-registration-service/ |
✅ | Internal-only /register gated by X-Internal-Caller: api-gateway, BCrypt, Postgres |
| Authentication Service | services/authentication-service/ |
✅ | /login issues PS256-signed access+refresh; /refresh is internal-only |
| Orders Service | services/orders-service/ |
✅ | REST + Kafka producer/consumer, pessimistic locks, idempotent fill tracking |
| Matching Engine | services/matching-engine/ |
✅ | Price–time priority, idempotency ledger, DLQ |
| Transaction Processor | services/transaction-processor/ |
✅ | Journals trade.executed.v1 → emits transaction.recorded.v1, REST queries |
| Portfolio Service | services/portfolio-service/ |
✅ | Projects transactions → positions & realized PnL; pessimistic locking + ledger |
| Market Data Consumer | services/market-data-consumer/ |
✅ | Kafka→Postgres OHLCV; Redis-cached “latest” with precise eviction |
| Docs: recruiter summary | CVREADME.md |
✅ | Hybrid, recruiter-friendly project overview |
| Docs: codebase review | CODEBASE_REVIEW_7POINTS.md |
✅ | Interview-oriented review of architecture, trade-offs, bugs, and redesign ideas |
| Docs: observability | docs/observability-stack-guide.md |
✅ | Metrics/logs/tracing/alerting implementation plan and readiness checklist |
| Docs: future work | docs/future-enhancements.md |
✅ | Prioritized roadmap for analytics, simulation bots, schema contracts, observability, infra |
| CI (GitHub Actions) | .github/workflows/ci.yml |
✅ | Docker Compose E2E checks for core flows |
| Roadmap delivery | — | 🔜 | Next work is documented, but not implemented: observability stack, analytics console, contracts, bot simulation, infra hardening |
| RabbitMQ option | — | ❌ | Not used—message bus is Kafka/Redpanda only |
| JWE (encrypted JWTs) | — | ❌ | Not used—project uses signed JWT (PS256) only |
Legend: ✅ present & working (dev), 🔜 planned, ❌ not applicable.
Clients
│
▼
API Gateway (8080) — PS256 JWT, Circuit Breakers, Redis Rate Limit (login), X-Request-Id
│
├─ /api/users/register → user-registration-service (8081) [internal header required]
├─ /api/auth/* → authentication-service (8082) [/login public, /refresh internal-only]
├─ /api/orders/* → orders-service (8085)
├─ /api/transactions/* → transaction-processor (8084)
├─ /api/portfolio/* → portfolio-service (8087)
└─ /api/market-data/* → market-data-consumer (8083)
Kafka/Redpanda (9092)
├─ order.placed.v1 → Matching Engine (8086) → trade.executed.v1
└─ trade.executed.v1 → Transaction Processor → transaction.recorded.v1 → Portfolio Service
- Language/Frameworks: Java 17/21, Spring Boot 3, Spring Cloud Gateway, Project Reactor
- Messaging: Kafka-compatible Redpanda
- Datastores: PostgreSQL (per service, Flyway migrations), Redis (rate limit + market latest)
- Resilience/Obs: Resilience4j circuit breakers, Spring Actuator
- Packaging: Docker & Docker Compose (local dev)
- Auth: JWT (PS256) at the gateway; private key in Auth service; public key at Gateway
- CI/CD/Cloud: GitHub Actions (E2E via Docker Compose); deployment/orchestration beyond local Compose is roadmap work, not in-repo
Start here depending on what you need:
README.md— current implementation overview and local runbookCVREADME.md— recruiter-facing summaryCODEBASE_REVIEW_7POINTS.md— architecture/trade-off/bug/redesign review for interview prepdocs/tradestream-prd.md— project requirements and architecture rationaledocs/api-design.md— gateway routes and service API behaviordocs/future-enhancements.md— concrete roadmap for simulation bots, analytics UI, schema governance, observability, and platform hardeningdocs/observability-stack-guide.md— implementation guide for metrics, logs, traces, lag dashboards, and alertingdocs/known-risks-and-non-goals.md— explicit current limitations, deferred scope, and implementation risks confirmed in codedocs/event-contracts.md— topic-by-topic Kafka contract details, idempotency behavior, and contract gapsdocs/security-model.md— current auth, trust boundaries, token model, and known security gapsdocs/test-strategy.md— what the current scripts and CI actually validate, plus drift and coverage gapsdocs/operational-runbook.md— local runtime troubleshooting guide for gateway, Kafka, Redis, and downstream servicesdocs/architecture-decisions.md— concrete architecture choices visible in the repo and their consequencesdocs/order-placement-matching-trade-execution-diagram.md— order placement to trade execution flowdocs/trade-execution-market-data-&-portfolio-updates-+-order-status-diagram.md— downstream projection/update flow
- Docker & Docker Compose
openssl(for JWT keypair)jq(nice to have)- (optional)
kcatfor Kafka testing
mkdir -p secrets
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out secrets/jwt_private.pem
openssl rsa -in secrets/jwt_private.pem -pubout -out secrets/jwt_public.pemdocker compose up -d --buildcurl -s http://localhost:8080/actuator/health
# {"status":"UP"}export DEMO_PASSWORD='<set-a-local-dev-password>'
curl -sS -X POST http://localhost:8080/api/users/register \
-H 'Content-Type: application/json' \
-d "{\"username\":\"alice\",\"password\":\"$DEMO_PASSWORD\"}"
ACCESS=$(curl -sS -X POST http://localhost:8080/api/auth/login \
-H 'Content-Type: application/json' \
-d "{\"username\":\"alice\",\"password\":\"$DEMO_PASSWORD\"}" | jq -r .access_token)
echo "ACCESS=$ACCESS"curl -sS -X POST http://localhost:8080/api/orders \
-H "Authorization: Bearer $ACCESS" -H 'Content-Type: application/json' \
-d '{"userId":"<uuid>","ticker":"AAPL","side":"BUY","type":"LIMIT","timeInForce":"GTC","quantity":10,"price":150.5}' | jq .curl -sS -H "Authorization: Bearer $ACCESS" \
http://localhost:8080/api/portfolio/<uuid>/positions | jq .
curl -sS -H "Authorization: Bearer $ACCESS" \
"http://localhost:8080/api/market-data/candles/AAPL/latest?interval=1m" | jq .Handy scripts live at repo root:
e2e_trade_pipeline_test.sh,e2e_portfolio_service.sh,gateway_smoke.sh.
GitHub Actions currently validates the stack using Docker Compose end-to-end checks:
- generates temporary JWT test keys for CI
- sets up JDK 21
- builds the API Gateway jar
- builds and starts the Compose stack
- waits for core services to become healthy before testing
- runs portfolio, trade pipeline, cancel flow, and scenario scripts
Primary workflow:
.github/workflows/ci.yml
Operationally relevant docs:
docs/observability-stack-guide.mdgateway_smoke.she2e_trade_pipeline_test.she2e_portfolio_service.she2e_scenarios.sh
The next tranche of work is already scoped in docs/future-enhancements.md and docs/observability-stack-guide.md. The most concrete items are:
- Observability implementation: Prometheus/Grafana, Loki, Jaeger/OpenTelemetry, lag dashboards, DLT alerting.
- Schema governance: Confluent Schema Registry and CI contract tests for
order.placed.v1,trade.executed.v1, andtransaction.recorded.v1. - Analytics console: Streamlit + Plotly ops dashboard for PnL, market data, bot activity, order flow, and risk.
- Bot market simulation: retail, market-maker, institutional, hedge, HFT, and portfolio bots to stress the event pipeline with richer market behavior.
- Platform hardening: stronger service-to-service auth, refresh-token rotation/revocation, per-user gateway limits, and eventual cloud/IaC work.
This keeps the README honest about what exists today while making the intended direction explicit for reviewers.
| Area | Route | Auth | Rewrites to… |
|---|---|---|---|
| Auth | POST /api/auth/login |
No | /login → authentication-service (8082) |
| Auth | POST /api/auth/refresh |
No | /refresh (internal-only header enforced) |
| Users | POST /api/users/register |
No | /register → user-registration (8081) |
| Orders | POST /api/orders |
Yes | /orders → orders-service (8085) |
| Orders | GET /api/orders/{id} |
Yes | /orders/{id} |
| Orders | POST /api/orders/{id}/cancel |
Yes | /orders/{id}/cancel |
| Transactions | GET /api/transactions/** |
Yes | (no rewrite) → transaction-processor (8084) |
| Portfolio | GET /api/portfolio/{userId}/positions[...] |
Yes | /portfolio/... → portfolio-service (8087) |
| Market Data | GET /api/market-data/candles/{ticker}[/latest] |
Yes | /candles/... → market-data-consumer (8083) |
| Ops | GET /actuator/health, GET /actuator/info |
No | Gateway itself |
| Ops | GET /actuator/gateway/**, GET /actuator/metrics |
Yes | Gateway itself |
- Login is IP rate-limited via Redis (token-bucket).
- Only
/actuator/healthand/actuator/infoare public; other actuator routes still require JWT. - Circuit breakers return predictable JSON fallbacks.
X-Request-Idinjected if missing; cookies stripped.
-
JWT at edge: Gateway is a resource server validating PS256 signatures with the public key.
-
Internal caller gates:
authentication-service/refreshrequiresX-Internal-Caller: api-gateway.user-registration-service/registerrequires the same header (added by the Gateway).
-
No JWE (encryption) — signed JWTs only.
-
Rate limiting: Redis-backed rate limit on login endpoints.
-
CORS: permissive in dev; tighten in prod (config in Gateway).
| Symptom | Likely cause | Fix |
|---|---|---|
401 at gateway |
Missing/expired/invalid JWT (PS256) | Re-login; verify public key mount |
429 on /api/auth/login |
Rate limit tripped | Back off; expected behavior |
Gateway degraded JSON (503) |
Circuit breaker open on downstream | Check downstream /actuator/health |
| Orders don’t execute | Matching Engine or Kafka not consuming | Inspect topics/consumer logs |
| Duplicate fills / position drift | Ledger/migration missing | Ensure Flyway applied; check unique constraints |
| Stale market “latest” | Quiet feed; TTL not expired | Next trade will evict → fresh read |
/register returns 403 |
Missing internal-caller header | Ensure Gateway injects X-Internal-Caller |
.
├── api-gateway/
├── services/
│ ├── authentication-service/
│ ├── user-registration-service/
│ ├── orders-service/
│ ├── matching-engine/
│ ├── transaction-processor/
│ ├── portfolio-service/
│ └── market-data-consumer/
├── docs/
├── docker-compose.yml
├── secrets/ # jwt_private.pem / jwt_public.pem
├── CVREADME.md # recruiter-facing overview
├── CODEBASE_REVIEW_7POINTS.md # architecture/trade-off/bug review
├── e2e_*.sh / gateway_smoke.sh
└── bench_out/
Per-service READMEs (sources of truth):
api-gateway/README.mdservices/authentication-service/README.mdservices/user-registration-service/README.mdservices/orders-service/README.mdservices/matching-engine/README.mdservices/transaction-processor/README.mdservices/market-data-consumer/README.md
This project is licensed under CC BY-NC 4.0. See LICENSE.