Design a Mobile Trading App: Real-Time Prices and Charting

“Design Robinhood” is a deceptively hard mobile system design question. The interviewer wants to see if you can handle real-time price feeds (10s of updates per second per ticker), accurate charting with 60fps scrubbing, an order placement flow that cannot lose orders, and a UI that feels alive without burning the battery.

Functional requirements

  • View portfolio with real-time mark-to-market
  • Search and view individual stocks/ETFs/crypto
  • Real-time price updates and charts
  • Place market and limit orders
  • Order status updates (placed, filled, cancelled)
  • News feed and notifications

Non-functional

  • Order placement: must never silently fail
  • Real-time prices: under 500ms from market to screen
  • Battery: streaming prices in the background must not drain noticeably

Architecture

Real-time prices over a single multiplexed WebSocket. Order placement over REST with idempotency keys. Portfolio state via REST + push updates.

Real-time price feed

Server pushes price updates for currently-visible tickers only. The client subscribes to the watchlist and currently-open chart, unsubscribes when out of view. Throttle on the server side — at most 5 updates per second per ticker, even if the underlying market data is faster.

Chart rendering

Use Metal (iOS) or Skia (cross-platform) for sub-pixel performance. Pre-aggregate candles server-side at multiple intervals (1m, 5m, 1h, 1d) so the client never has to compute aggregations. Smooth scrubbing uses interpolation between sample points.

Order placement

Critical path. Client generates a UUID idempotency key, posts to /orders, and waits up to 5 seconds. If timeout, retry with the same UUID — server dedupes and returns the existing order if seen.

UI shows an explicit “submitting” state and never optimistically confirms. Confirmed only when server returns order_id.

Order updates

Server pushes order status changes via the same WebSocket. Client also polls every N seconds when foreground as a backup, in case WebSocket is silently dead.

Local persistence

Last-known portfolio cached in SQLite. On cold start, render cached state immediately, then refresh from server. Order history is server-of-record; local store is a cache only.

Battery

  • Disconnect WebSocket when app backgrounded
  • Push notifications for order fills, not via persistent connection
  • Throttle chart redraws to 30fps when scrolling, 60fps when scrubbing

Frequently Asked Questions

What if the user places an order while offline?

Disable order placement when network is unavailable. Trading is too risky to queue offline. Show a clear error and require the user to retry.

How do you handle market open/close?

Server pushes a market-state event. Client greys out trading actions outside market hours and shows last-traded price with a “closed” indicator.

How accurate are mobile prices?

Most retail apps stream IEX or vendor-aggregated feeds with ~100ms delay. True low-latency feeds are reserved for institutional clients.

Scroll to Top