Modularity
A system is modular when each component owns a single responsibility and exposes a contract. You can replace the execution engine without rewriting the signal engine. You can swap exchanges without touching the risk layer.
Why it matters in trading systems
Trading systems change constantly. New venues, new instruments, new regulatory constraints. A monolithic execution layer becomes a liability the first time you need to add an exchange with a different order model. Modularity buys you the ability to change parts without breaking the whole.
The trade-off
Modularity adds indirection. Every contract is a place where assumptions get lost. Too many small services and latency suffers, deployments multiply, and debugging requires tracing across boundaries. The goal is not maximum decomposition — it is decomposition along the axes of actual change.
How I apply it
Decompose by what changes independently: venues, instruments, strategies, risk rules. Keep the execution path short. Keep cross-module contracts minimal. Reject abstractions that exist only in case they are needed later.
Failure Handling
Every component fails. Exchanges disconnect. Database writes partially complete. Orders send but acknowledgements never arrive. A system that is honest about this is designed around failure, not against it.
Core techniques
- idempotent operations
- client-side order IDs
- retry with backoff
- compensating transactions
- dead-letter queues
- explicit timeout budgets
The trade-off
Retries create duplicates. Compensations create inconsistent intermediate states. Defensive coding hides bugs. Every failure strategy has a cost — the question is whether you pay it in code complexity, latency, or financial exposure.
The rule I use
If an operation affects capital, it must be idempotent at the client. Server-side deduplication is not enough. The client owns the intent, and the intent must survive a retry.
Data Consistency
Trading systems span multiple state stores: exchange state, local state, settlement state, accounting state. Consistency is the question of how long these can disagree before the system breaks.
Strong vs eventual consistency
Strong consistency means every read sees the last write. Eventual consistency means reads may be stale but converge. Strong is expensive in latency and availability. Eventual is cheap but forces every consumer to handle staleness.
What trading execution requires
Position state must be strongly consistent within the execution path — you cannot place an order based on a stale position. But market data and monitoring can be eventually consistent. The boundary between strong and eventual is a design decision, and it almost always runs along the risk layer.
The trade-off
Pushing strong consistency further out buys safety and costs latency. Pulling it inward buys speed and costs correctness. The answer depends on what a wrong decision costs — for a position check, correctness wins. For a P&L display, speed wins.
Latency vs Reliability
You can have low latency or high reliability. You cannot always have both. Every retry, every validation, every durability guarantee adds latency. Every latency optimization weakens a reliability guarantee.
When to choose latency
When the edge depends on it. Market making, arbitrage, latency-sensitive execution — missing a window has a direct cost. Here the system accepts failures and handles them asynchronously, because waiting is the bigger loss.
When to choose reliability
When the downside is larger than the opportunity. Settlement, reconciliation, compliance, user-facing withdrawals. Here the system waits for confirmation, persists state before acknowledging, and prefers correctness over throughput.
How to hedge both
Split the system along this axis. The hot path is latency-optimized, narrow, and allowed to fail. The cold path is reliability-optimized, durable, and the source of truth. The hot path reports to the cold path — never the inverse.
Risk as a System Layer
Risk is not a check. It is a layer. A check runs once, at a single point, and passes or fails. A layer spans the entire system — pre-trade, at-trade, post-trade, intraday, end-of-day — and enforces invariants that no other component is allowed to violate.
Why checks fail
A pre-trade check validates an order in isolation. It does not know the order that executed 50ms ago, or the position that is currently being updated, or the exposure building up across venues. Checks catch obvious errors. They do not catch systemic drift.
What a risk layer enforces
- position limits
- exposure limits across venues
- rate limits on order submission
- drawdown triggers
- kill switches
- reconciliation against truth sources
The trade-off
A risk layer adds latency to every path that touches it. Done wrong, it becomes the bottleneck that makes the system uncompetitive. Done right, it is invisible until it saves you — and that is the day it pays for its entire build cost.
Ignacio Montoya is a systems architect specializing in algorithmic trading infrastructure, financial systems, and digital asset platforms. These principles guide every engagement — from architecture reviews to full systems builds.
If your system violates two of these principles, you already know where the next incident is coming from. If it violates three, we should have talked yesterday.
Engagement model