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

Source: https://www.techinterview.org/post/3233474990/design-mobile-trading-app-robinhood/
Updated: 2026-07-26 · techinterview.org

"Design Robinhood" is a deceptively hard [mobile system design question](/system-design-interview-guides/). 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. Every holding needs its current value recomputed as prices tick, along with day change and total gain/loss. Interviewers probe how you keep the aggregate portfolio total consistent when dozens of positions update at slightly different moments.

- Search and view individual stocks/ETFs/crypto. Search has to feel instant, so debounce keystrokes and hit a typeahead endpoint backed by a prefix index over symbols and company names. The detail view is where you attach the live price stream and chart for a single symbol.

- Real-time price updates and charts. This is the heart of the question: prices arrive continuously and the chart has to reflect them without jank. Be ready to discuss how a visible symbol subscribes to the feed and how the chart appends a new point versus fully redrawing.

- Place market and limit orders. A market order fills at the current price; a limit order rests until the price crosses a set threshold. Interviewers want you to validate buying power and quantity on the client for fast feedback, then treat the server as the final authority on whether the order is accepted.

- Order status updates (placed, filled, cancelled). An order moves through these states asynchronously, sometimes seconds after submission, so the client needs a push channel plus a fallback to reconcile. Walk through the full lifecycle, including partial fills and rejections, not just the happy path.

- [News feed](/post/3233474168/system-design-twitter-news-feed-timeline-fanout-on-write-fanout-on-read-celebrity-problem-ranking-caching/) and notifications. Show per-symbol headlines plus account-level alerts like fills and price targets. If the interviewer pushes on delivering these to millions of users, it becomes a fan-out problem worth calling out.

## Non-functional

- Order placement: must never silently fail. The failure mode to avoid is the user tapping buy, seeing nothing, and not knowing whether an order went through. Every path — timeout, network drop, server error — has to resolve to a clearly confirmed or rejected state.

- Real-time prices: under 500ms from market to screen. Budget this end to end across feed ingestion, server fan-out, network, and render. If asked, name where the latency goes and which hop you would optimize first.

- Battery: streaming prices in the background must not drain noticeably. A persistent socket and constant redraws are the usual culprits. The expected answer is to tear down streaming when the app leaves the foreground and rely on push notifications instead.

## 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](/post/3233474159/system-design-rate-limiter-token-bucket-sliding-window-leaky-bucket-distributed-rate-limiting-api-gateway/) — 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.
