Implementing Order Book in Mobile Exchange Applications
An order book is one of the most performance-demanding components in exchange apps. Data updates several times per second, the list may contain hundreds of price levels, and the UI must remain responsive.
Data Source: WebSocket
Exchange order books update via WebSocket—HTTP polling is unacceptable due to latency. Standard approach: get a snapshot via REST, then subscribe to incremental updates via WebSocket.
Example for Binance API (pattern used by most exchanges):
GET https://api.binance.com/api/v3/depth?symbol=BTCUSDT&limit=100
→ snapshot with full bids and asks
WSS wss://stream.binance.com:9443/ws/btcusdt@depth@100ms
→ incremental updates every 100ms
Applying incremental updates: if a price level exists in the book, update its quantity. If quantity is 0, remove the level. If price is new, add it. This is a standard diff algorithm for order books.
Snapshot and Stream Synchronization
A critical moment often implemented incorrectly: WebSocket begins sending updates before the REST snapshot request completes. Buffer WS events, get the snapshot with its lastUpdateId, then apply only buffered events where firstUpdateId <= lastUpdateId + 1.
Lost an event? Out of sync? The only solution is to reconnect and get a new snapshot. Don't attempt to recover state from partial data.
Rendering: The Main Problem
100 price levels × updates every 100ms = potential UI lag. On mobile, this is especially noticeable.
Don't update the list on every WebSocket event. Batching: accumulate updates and apply to UI every 250–500ms. Users won't notice the difference between 100ms and 250ms, but it's 2.5x less work for the renderer.
Virtualization. Display only visible levels, don't render all 100. On iOS, use UITableView with reloadRows(at:with:) for changed rows, not reloadData(). On Android, use RecyclerView with DiffUtil to compute minimal changes. In Flutter, use ListView.builder with itemCount.
Colors and change highlights: when price drops—red, up—green, then smoothly return to neutral. Implement via color animation with CABasicAnimation (iOS) or ValueAnimator (Android). Don't use per-row timers—use one timer for the entire list.
Order Book Depth: Depth Chart
Visualize volumes with an accumulated histogram (depth chart)—accumulate volume from best to worst price. Draw via CAShapeLayer / Canvas / CustomPainter in Flutter. Update no more than once per second—this is visualization, not a trading tool.
Number Precision
Exchange prices and volumes are decimals with high precision. BTC trades with 8 decimal places. No Double—only Decimal (iOS) or BigDecimal (Android). Summing volumes with Double creates noticeable rounding errors when displayed.
Formatting: different trading pairs have different tick sizes (minimum price step). BTC/USDT has tick size 0.01, some altcoins have 8 decimal places. Get the number of decimal places from pair metadata, not hardcode.
Offline and Reconnection
On connection loss, clear the book and show "No data / Reconnecting". Don't show a stale book as current—this misleads traders.
Reconnection logic: exponential backoff from 1s to 30s. After recovery, get a fresh snapshot and resubscribe.
Timeline: implementing order book with WebSocket, correct synchronization, and optimized rendering—2–3 weeks. With depth chart, sorting, depth filtering, and support for multiple trading pairs—4–5 weeks.







