-
Notifications
You must be signed in to change notification settings - Fork 12
Design Patterns
tien.nguyen edited this page Jul 30, 2026
·
1 revision
The Emporia Trading Platform incorporates enterprise architectural and object-oriented design patterns to ensure low latency, high throughput, maintainability, and strict concurrency safety.
-
Implementation:
gatewaymodule using Spring Cloud Gateway. -
Role: Single entry point for external client traffic (
:8082). Handles OIDC authentication header injection, CORS configuration, path-based routing (/api/static/**,/api/orders/**,/api/market-data/**), and rate limiting.
-
Implementation:
trading-contracts,order-command-service,order-management-service,execution-service. -
Role: Asynchronous, non-blocking communication using Apache Kafka topics (
emporia.order.commands.v1,emporia.order.results.v1,emporia.orders.v1,emporia.execution.commands.v1). Decouples command issuance from state persistence and execution routing.
-
Implementation:
-
Command Path:
order-command-servicereceivesPOST /api/orderscommands, validates them, and produces immutable Kafka commands. -
Query Path:
order-management-servicemaintains read-optimized database models (TradingOrder) queried viaGET /api/orders/{id}andGET /api/orders.
-
Command Path:
-
Implementation: Separate PostgreSQL databases (
emporia_authorisation,emporia_static_data,emporia_client_config,emporia_order_data,emporia_portfolio). - Role: Ensures strict domain boundary isolation, preventing tight database coupling and allowing independent service scaling.
- Implementation: Distributed order lifecycle processing across Kafka topic channels without a centralized orchestrator.
-
Role:
OrderCommandService$\rightarrow$ OrderManagementService$\rightarrow$ ExecutionService$\rightarrow$ OrderManagementService$\rightarrow$ PortfolioService. Each service reacts to events and publishes state transitions.
| Pattern | Location / Class | Architectural Role & Purpose |
|---|---|---|
| Strategy Pattern |
execution-service (OrderRoutingStrategy, SmartRoutingStrategy, VwapRoutingStrategy) |
Dynamically selects order routing logic based on order type, size, and market execution conditions. |
| State Machine Pattern |
order-management-service (TradingOrder) |
Enforces valid status transitions (PENDING_NEW LIVE PARTIALLY_FILLED FILLED / CANCELLED / REJECTED) and mathematical quantity invariants. |
| Observer Pattern |
market-data-service (QuoteAggregator, MarketDataSseController) |
Broadcasts streaming tick updates and aggregated depth updates to connected client subscribers via HTTP SSE and gRPC streams. |
| Adapter Pattern |
execution-service (ExchangeCoreAdapter) |
Bridges Emporia's Kafka order events to the in-memory LMAX Disruptor exchange-core matching engine protocol. |
| Facade Pattern |
order-command-service (StaticDataClient) |
Provides a simplified fluent RestClient interface to query instrument snapshots from static-data-service. |
| Decorator Pattern |
market-data-service (ResilientMarketDataProvider) |
Wraps external IEX / FIX market data sources with fallback logging, retry mechanisms, and rate limit guards. |
The TradingOrder entity in order-management-service implements thread-safe state machine transitions:
public synchronized void applyFill(BigDecimal fillQuantity, BigDecimal fillPrice) {
require(status == OrderStatus.LIVE || status == OrderStatus.PARTIALLY_FILLED
|| status == OrderStatus.CANCELLED,
"Only active or cancelled orders can receive fills");
// Recalculate traded quantity, remaining quantity, and volume-weighted average price
BigDecimal newTradedQuantity = tradedQuantity.add(fillQuantity);
tradedQuantity = newTradedQuantity;
remainingQuantity = quantity.subtract(newTradedQuantity);
averageTradePrice = newTradeValue.divide(newTradedQuantity, 6, RoundingMode.HALF_UP);
if (remainingQuantity.signum() == 0) {
status = OrderStatus.FILLED;
} else if (status != OrderStatus.CANCELLED) {
status = OrderStatus.PARTIALLY_FILLED;
}
validateInvariants();
}-
Thread Safety: All state-modifying methods (
applyFill,requestCancel,confirmCancel,reject) usesynchronizedmonitors. -
Invariant Enforcement:
validateInvariants()guarantees thattradedQuantity + remainingQuantity == quantityat all times. - Late Fill Safety: Accepts late fills received from execution venues even after order cancellation.
- Trading Terminology Glossary
- Order Lifecycle & Validation
- Order Routing & SOR
- Market Data & Pricing
- Portfolio & Risk Management
- Architecture & Order Flow
- Static Data Service
- Market Data Service
- Order Command Service
- Order Management Service (OMS)
- Execution Service
- Portfolio Service
- Design Patterns
- Microservices Overview
- Exchange-Core Integration
- Testing & Verification
- Deployment & Operations
- Repository: emporia
- Tech Stack: Java 21 | Spring Boot 4.0.7 | React 19 | Kafka | gRPC
- Coverage: 91.95% JaCoCo