A trading bot prototype can be very small:
market data → strategy → order
A production-oriented trading system is very different.
Once real-time market data, orderbook state, execution, retries, order lifecycle and reconciliation enter the picture, the architecture becomes a backend engineering problem.
This article explains how I'm structuring the backend of a Polymarket trading bot and, more importantly, why I keep the major responsibilities separated.
The Architecture
The current architecture can be summarized as:
MARKET DATA
│
▼
ORDERBOOK STATE
│
▼
STRATEGY
│
▼
RISK / POSITION
│
▼
EXECUTION ENGINE
│
▼
ORDER MANAGEMENT
│
▼
RECONCILIATION
│
▼
MONITORING
The key idea is that each layer has a distinct responsibility.
The strategy decides what should happen.
The execution layer decides how it should happen.
The reconciliation layer makes sure the system's internal state remains consistent with the external trading state.
1. Market Data Layer
The first problem is getting reliable market data into the application.
A real-time trading system needs to handle more than receiving messages.
It also has to deal with:
- WebSocket disconnects
- reconnects
- missed events
- message ordering
- stale data
- local state reconstruction
- synchronization
A healthy WebSocket connection does not automatically mean that the application has trustworthy market state.
For that reason, I treat market-data ingestion as its own backend component rather than putting it directly inside strategy logic.
A simplified flow looks like:
WebSocket / API
│
▼
Market Data Worker
│
▼
Normalized Market Events
│
▼
Orderbook / Market State
The normalization step is important because downstream components should not need to understand every detail of the transport layer.
2. Orderbook State
The orderbook is one of the most important inputs to the trading system.
The challenge is time.
The application observes market state at one point and execution happens later.
That means the system needs to understand whether the state it is using is still valid for the execution decision.
I encountered this problem directly while building my Polymarket trading bot.
A stale-orderbook issue caused execution assumptions to be based on outdated market information.
I documented that case separately:
Polymarket Trading Bot Execution: Fixing Stale Orderbook Fills
That experience changed how I think about the boundary between market-data processing and execution.
3. Strategy Layer
The strategy should primarily answer:
What should I do?
For example:
Market condition
│
▼
Strategy
│
▼
Execution Intent
The strategy should not need to know:
- how an order is retried
- how partial fills are handled
- how cancellation works
- how reconciliation works
- how a failed connection is recovered
Those are execution concerns.
This separation allows the strategy to change without forcing large changes across the rest of the backend.
4. Risk and Position
Before an execution intent becomes an order, the system may need to validate:
- current position
- available balance
- exposure
- existing orders
- execution limits
- risk rules
The flow becomes:
Strategy
│
▼
Execution Intent
│
▼
Risk Validation
│
▼
Execution
Keeping this boundary explicit makes the system easier to reason about and test.
5. Execution Engine
This is where the trading bot becomes an execution system.
The strategy says:
I want to execute this.
The execution engine answers:
How should I execute it reliably?
That can involve:
- order creation
- timing
- retries
- cancellation
- partial fills
- price changes
- execution constraints
- TWAP
I prefer keeping these concerns out of strategy code.
It means the strategy can focus on decision-making while the execution engine focuses on getting the requested action completed correctly.
6. Order Management
An order isn't simply:
created → done
The system can have a lifecycle such as:
CREATED
↓
SUBMITTING
↓
OPEN
↓
PARTIALLY_FILLED
↓
FILLED
Or:
OPEN
↓
CANCEL_REQUESTED
↓
CANCELLED
Or:
SUBMITTING
↓
FAILED
↓
RETRY
Explicit order states are useful because execution logic becomes much easier to reason about than if state is spread across unrelated flags and callbacks.
7. Reconciliation
The application maintains its own view of:
- orders
- fills
- positions
- balances
The external trading system maintains another view.
Those two states can diverge.
For example:
Internal state → ORDER = OPEN
External state → ORDER = FILLED
A reconciliation process can detect that difference and bring the internal model back into alignment.
This becomes especially important after:
- timeouts
- disconnects
- failed requests
- partial fills
- application restarts
For me, reconciliation is one of the clearest signs that a trading bot has moved beyond a simple script.
8. Backend Infrastructure
As the system grows, the components can be separated into workers and persistent services.
A simplified version looks like:
┌─────────────────────┐
│ WebSocket / API │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Market Data Worker │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Market State / │
│ Orderbook Processor │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Queue / Redis │
└───────┬─────┬───────┘
│ │
┌─────────┘ └─────────┐
▼ ▼
┌──────────────────┐ ┌──────────────────┐
│ Strategy Worker │ │ Execution Worker │
└────────┬─────────┘ └────────┬─────────┘
│ │
│ Execution Intent │ Orders
└────────────┬─────────────┘
▼
┌─────────────────┐
│ Order Management│
└────────┬────────┘
│
┌────────┴────────┐
▼ ▼
┌──────────────┐ ┌───────────────┐
│ PostgreSQL │ │ Reconciliation│
│ Durable State│ │ Worker │
└──────────────┘ └──────┬────────┘
│
▼
External / Polymarket
│
▼
Reconciliation Result
│
▼
Internal State Update
┌─────────────────────────────────────────────────┐
│ Monitoring / Observability │
│ Logs · Metrics · Alerts · Execution Monitoring │
└─────────────────────────────────────────────────┘
▲ ▲ ▲
│ │ │
Market Data Workers Orders/State
The exact implementation depends on the system requirements, but the architectural responsibilities remain the same:
- ingest events
- maintain state
- process execution intents
- persist durable information
- recover from failures
- expose operational information
9. Monitoring and Observability
A trading backend should be able to explain what happened.
For an individual order, I want to be able to answer:
- Why did the strategy create it?
- What market state existed at that moment?
- What happened during execution?
- Was it retried?
- Was it partially filled?
- Did reconciliation change the state?
That requires useful:
- logs
- metrics
- alerts
- execution history
- error reporting
Observability is part of the backend design, not something I want to add after the system is already difficult to debug.
10. Why This Architecture Matters
The main lesson from building this system is that the strategy is only one component.
The harder engineering problems tend to appear at the boundaries:
market data ↔ orderbook
strategy ↔ execution
execution ↔ order state
internal state ↔ external state
Those boundaries are where stale data, timing issues, retries and state divergence become real production problems.
That is why I prefer an architecture with explicit responsibilities rather than a single large trading-bot process.
What's Next
I'm continuing to build and document this system around:
- Polymarket trading bots
- market-data infrastructure
- orderbook systems
- execution engines
- TWAP
- order management
- reconciliation
- monitoring
- scalable trading-system backends
The next step is to go deeper into the market-data and WebSocket layer and how it feeds reliable execution decisions.
Resources
Polymarket Trading Bot Execution: Fixing Stale Orderbook Fills
Top comments (0)