Design Robinhood
Robinhood is a commission-free stock trading platform that democratizes access to financial markets. It allows users to buy and sell stocks, ETFs, options, and cryptocurrencies from their smartphones, offering real-time market data, instant trade execution, and portfolio management features.
Designing Robinhood presents unique challenges including real-time market data streaming, order execution with microsecond latency, regulatory compliance (SEC, FINRA), portfolio valuation at scale, and handling extreme market volatility during events like the GameStop squeeze.
Step 1: Understand the Problem and Establish Design Scope
Before diving into the design, it’s crucial to define the functional and non-functional requirements. For trading platforms, we need to balance user experience with regulatory compliance and financial accuracy.
Functional Requirements
Core Requirements (Priority 1-5):
- Users should be able to view real-time stock quotes and market data for thousands of securities.
- Users should be able to place market orders, limit orders, and stop-loss orders.
- Users should be able to view their portfolio with real-time valuations and performance metrics.
- Users should be able to buy fractional shares (e.g., buy $10 worth of AAPL).
- Users should be able to trade on margin with real-time buying power calculations.
Below the Line (Out of Scope):
- Users should be able to trade options (calls and puts).
- Users should be able to set up recurring investments.
- Users should be able to access historical charts and technical indicators.
- Users should be able to receive personalized stock recommendations.
- Users should be able to participate in IPOs.
Non-Functional Requirements
Core Requirements:
- The system should provide real-time market data with latency < 500ms from exchange to user.
- The system should execute trades with high reliability (99.99% success rate during market hours).
- The system should ensure strong consistency for account balances and positions to prevent overdrafts.
- The system should handle high throughput during market open/close (1M+ orders per minute).
- The system must be compliant with SEC regulations (Reg T for margin), FINRA rules, and maintain audit trails.
Below the Line (Out of Scope):
- The system should implement robust fraud detection and AML (Anti-Money Laundering) checks.
- The system should support disaster recovery with RPO < 1 minute and RTO < 5 minutes.
- The system should provide comprehensive monitoring and alerting for all financial operations.
- The system should support gradual rollouts and A/B testing without affecting trade execution.
Clarification Questions & Assumptions:
- Platform: Primary focus on mobile apps (iOS/Android), with web support.
- Scale: 30 million users, with approximately 5 million active traders. Peak trading volume during market open (9:30 AM ET).
- Asset Classes: Stocks, ETFs, and fractional shares. Options and crypto mentioned but out of detailed scope.
- Market Hours: US markets (9:30 AM - 4:00 PM ET), with extended hours trading (4:00 AM - 9:30 AM, 4:00 PM - 8:00 PM).
- Settlement: T+2 settlement cycle (trade date plus 2 business days).
- Clearing: Use third-party clearing houses (Apex Clearing, Clearing Corps).
Step 2: Propose High-Level Design and Get Buy-in
Planning the Approach
For financial applications, we’ll organize our design around critical data flows: market data ingestion and distribution, order placement and execution, portfolio management, and regulatory compliance. Each flow has strict latency and consistency requirements.
Defining the Core Entities
To satisfy our key functional requirements, we’ll need the following entities:
User: Platform user with personal information, KYC (Know Your Customer) verification status, tax information (SSN/ITIN), account type (individual, IRA, margin), and trading permissions.
Account: Financial account linked to a user. Tracks cash balance, buying power, margin usage, and settled/unsettled funds. A user can have multiple accounts (e.g., brokerage, IRA).
Position: Represents ownership of a security. Includes ticker symbol, quantity (can be fractional), cost basis, average purchase price, and timestamps. Essential for portfolio valuation and tax reporting.
Order: A request to buy or sell a security. Contains order type (market/limit/stop), side (buy/sell), quantity, limit price (if applicable), time-in-force (day/GTC), status (pending/filled/cancelled), and execution details.
Trade: A completed execution of an order. Records the execution price, quantity, timestamp (microsecond precision), venue (which exchange), and fees. Multiple trades can fulfill a single order.
Security: Reference data for tradable instruments. Includes ticker symbol, company name, exchange listing, security type (stock/ETF), current price, bid/ask spread, market cap, and trading status (open/halted/closed).
MarketData: Real-time and historical price information. Includes ticker, price, bid/ask, volume, timestamp, and may include Level 1 (top of book) or Level 2 (order book depth) data.
API Design
Get Real-Time Quote Endpoint: Returns current price and market data for a security.
GET /quotes/:symbol -> Quote
The response includes symbol, price, bid, ask, bidSize, askSize, volume, timestamp, and marketStatus (open, closed, pre, or post).
Place Order Endpoint: Submits a new order for execution.
POST /orders -> Order
The body includes symbol, side (buy or sell), orderType (market, limit, or stop_loss), quantity (can be fractional), optional limitPrice for limit orders, optional stopPrice for stop orders, and timeInForce (day, gtc, ioc, or fok).
The endpoint performs pre-trade compliance checks (sufficient buying power, pattern day trader rules, position limits) before accepting the order.
Get Portfolio Endpoint: Returns user’s current holdings with real-time valuations.
GET /portfolio -> Portfolio
The response includes accountValue, cashBalance, buyingPower, positions array with symbol details, quantity, costBasis, currentPrice, marketValue, unrealizedGain, unrealizedGainPercent for each position, dayChange, and dayChangePercent.
Get Account Endpoint: Returns account details including margin information.
GET /account -> Account
The response includes accountNumber, accountType (cash or margin), cashBalance, buyingPower, marginUsed, maintenanceMargin, settledFunds, unsettledFunds, daytradingBuyingPower, and optionsBuyingPower.
WebSocket Connection for Real-Time Streaming:
WS /stream
Clients subscribe with an action and array of symbols. Messages are pushed to subscribed clients with type, symbol, price, bid, ask, and timestamp.
High-Level Architecture
Let’s build up the system sequentially, addressing each functional requirement:
1. Users should be able to view real-time stock quotes and market data
The core components for market data are:
- Client App: Mobile (iOS/Android) and web clients that display market data and charts.
- API Gateway: Entry point with authentication, rate limiting, and request routing. Handles both HTTP and WebSocket connections.
- Market Data Service: Manages real-time and historical price data. Aggregates data from multiple sources and normalizes it for client consumption.
- Market Data Feed Handler: Ingests raw market data feeds from exchanges (NYSE, NASDAQ) and data vendors (IEX Cloud, Polygon.io). Parses binary protocols like FIX or SIP.
- WebSocket Gateway: Maintains persistent connections with clients for real-time streaming. Publishes price updates to subscribed clients with sub-second latency.
- Market Data Cache: High-speed cache (Redis) storing latest quotes for thousands of securities. Enables fast lookups without querying databases.
- Time Series Database: Stores historical market data for charting and analysis (InfluxDB, TimescaleDB, or Clickhouse).
Market Data Flow:
- Exchanges (NYSE, NASDAQ) and data providers publish market data via FIX protocol or REST APIs.
- The Market Data Feed Handler consumes these feeds, normalizes the data format, and enriches it with metadata.
- Processed data is published to a message queue (Kafka topic: market-data-updates).
- The Market Data Service consumes from Kafka and updates the Market Data Cache with latest prices.
- The WebSocket Gateway subscribes to the same Kafka topic and pushes updates to connected clients in real-time.
- Historical data is persisted to the Time Series Database for charting and backtesting.
Client Request Flow:
- User opens the app and searches for a stock (e.g., “AAPL”).
- Client sends GET /quotes/AAPL to the API Gateway.
- Market Data Service checks the cache for the latest quote and returns it.
- Client establishes WebSocket connection and subscribes to AAPL for real-time updates.
- As new price data arrives, WebSocket Gateway pushes updates to the client instantly.
2. Users should be able to place market orders, limit orders, and stop-loss orders
We introduce components for order management and execution:
- Order Service: Manages order lifecycle (creation, validation, modification, cancellation). Performs pre-trade compliance checks.
- Order Management System (OMS): Central repository for all orders. Tracks order status and maintains order history.
- Order Router: Routes orders to appropriate execution venues. Implements smart order routing (SOR) to find best execution prices.
- Broker API / FIX Gateway: Interfaces with clearing brokers and market makers via FIX protocol for actual trade execution.
- Position Service: Tracks real-time positions and updates them as trades execute. Ensures position consistency.
- Compliance Engine: Validates orders against regulatory rules (pattern day trader, position limits, restricted securities).
Order Placement Flow:
- User enters order details in the app and taps “Review Order”.
- Client displays order preview with estimated cost and impact on buying power.
- User confirms, sending POST /orders request.
- API Gateway authenticates and forwards to Order Service.
- Order Service performs pre-trade checks:
- Verify sufficient buying power (query Account Service).
- Check trading hours and market status.
- Validate against compliance rules (Compliance Engine).
- Check for pattern day trader restrictions.
- If checks pass, Order Service creates order record in OMS database with status “pending”.
- Order is published to Kafka topic orders-pending for asynchronous processing.
- Order Router consumes the order and determines optimal execution venue.
- Order Router sends execution request to Broker API via FIX protocol.
- Order Service returns Order object to client with order ID and status.
Order Execution Flow:
- Broker executes the order at the market (for market orders) or waits for price target (limit orders).
- Execution confirmations (fills) are received via FIX protocol.
- Fill Handler processes the fill and publishes to Kafka topic trades-executed.
- Order Service updates order status to “filled” in OMS.
- Position Service updates user positions with new holdings.
- Account Service debits/credits cash balance.
- Client receives real-time notification via WebSocket about the fill.
3. Users should be able to view their portfolio with real-time valuations
We extend our design for portfolio management:
- Portfolio Service: Calculates portfolio valuations, performance metrics, and analytics. Combines position data with real-time market prices.
- Account Service: Manages account balances, buying power, and margin calculations. Enforces account-level constraints.
- Positions Database: Stores user positions with cost basis and quantity. Supports fractional shares.
Portfolio Calculation Flow:
- User opens the portfolio screen in the app.
- Client sends GET /portfolio request.
- Portfolio Service queries Position Service for all user positions.
- For each position, Portfolio Service fetches current price from Market Data Cache.
- Portfolio Service calculates:
- Market value = quantity × current price
- Unrealized gain = market value - cost basis
- Total portfolio value = sum of all positions + cash balance
- Results are enriched with day change, percent change, and diversification metrics.
- Portfolio snapshot is cached with TTL of 1 second for performance.
- Response is returned to client.
Real-Time Updates:
- As market data updates arrive, Portfolio Service recalculates affected positions.
- Updated portfolio valuations are pushed to clients via WebSocket.
- Clients update UI in real-time without requiring refresh.
4. Users should be able to buy fractional shares
Fractional shares allow users to invest with small amounts. We need special handling:
- Fractional Shares Engine: Aggregates fractional orders into whole share orders for execution. Maintains internal ledger of fractional ownership.
Fractional Share Flow:
- User selects “Buy in dollars” and enters $50 for AAPL trading at $180.
- Order Service calculates fractional quantity: $50 / $180 = 0.2777 shares.
- Order is marked as fractional and stored in OMS.
- Fractional Shares Engine aggregates multiple fractional orders (from different users) throughout the day.
- When total reaches 1+ whole shares, engine places a bulk order for whole shares.
- After execution, fractional shares are allocated proportionally to users.
- User receives 0.2777 shares in their account.
Challenges:
- Allocating execution price fairly across users.
- Handling partial fills of bulk orders.
- Managing rounding errors to prevent account discrepancies.
- Ensuring regulatory compliance (fractional shares must be held at clearing firm).
5. Users should be able to trade on margin with real-time buying power calculations
Margin trading allows users to borrow money to buy more securities:
- Margin Service: Calculates margin requirements, buying power, and monitors margin health. Enforces Regulation T requirements.
- Risk Management Service: Monitors account risk in real-time. Triggers margin calls when maintenance margin is breached.
Margin Calculation Flow:
- User requests account details: GET /account.
- Margin Service calculates buying power:
- For Reg T margin: Buying Power = (Cash + (0.5 × Marginable Securities)) × 2
- Pattern Day Trader: 4× buying power (with restrictions)
- Margin Service calculates margin used:
- Margin Used = (Position Value - Cash) where position was bought on margin
- Maintenance Margin = 25% of position value (or higher for volatile stocks).
- If Account Value < Maintenance Margin + Margin Used, trigger margin call.
Margin Call Flow:
- Risk Management Service monitors accounts in real-time.
- When maintenance margin is breached, system generates margin call.
- User is notified via app notification, email, and SMS.
- User has typically 2-5 days to deposit funds or liquidate positions.
- If user doesn’t respond, system automatically liquidates positions to cover margin.
Step 3: Design Deep Dive
With the core functional requirements met, it’s time to dig into the non-functional requirements and critical subsystems.
Deep Dive 1: How do we stream real-time market data to millions of users with low latency?
Real-time market data is the foundation of any trading platform. We need to deliver price updates with sub-second latency while serving millions of concurrent users.
Challenge:
During market hours, major exchanges generate millions of quote updates per second. NYSE alone can produce 10M+ messages/second during high volatility. We need to:
- Ingest high-velocity data feeds
- Process and normalize data from multiple sources
- Distribute to millions of WebSocket connections
- Maintain < 500ms latency from exchange to user
Solution: Multi-Tier Streaming Architecture
Tier 1: Feed Handler Layer
Deploy specialized feed handlers that connect directly to exchange feeds:
- Direct Exchange Feeds: Connect to NYSE, NASDAQ via dedicated lines (expensive but fastest).
- Data Vendors: Use aggregated feeds from IEX Cloud, Polygon.io, or Intrinio (cost-effective for retail).
- FIX Protocol: Many brokers receive executions via FIX 4.2/4.4 or newer versions.
Feed handlers are written in low-latency languages (C++, Rust) and parse binary protocols efficiently. In a continuous loop, the handler receives messages from the socket, parses them using the appropriate protocol (FIX, SIP, or IEX), normalizes the quote structure to include symbol, price, bid, ask, volume, timestamp, and exchange, then publishes this normalized quote to a Kafka topic called market-data-raw.
Tier 2: Data Processing Layer
Consume raw feed data, apply business logic, and enrich:
- Deduplication: Multiple feeds may report the same quote. Dedupe based on timestamp and exchange.
- Conflation: If a stock updates 100 times per second but clients only need 1 update/second, conflate (keep latest in time window).
- Enrichment: Add company name, market cap, PE ratio from reference data.
- Validation: Detect erroneous prices (circuit breakers, bad ticks).
Use stream processing frameworks:
- Kafka Streams: Process data in-place with stateful operations.
- Apache Flink: For complex event processing and windowing.
- In-House Solutions: Some firms build custom C++ processors for ultimate performance.
Tier 3: Distribution Layer
Distribute processed quotes to connected clients:
Option 1: WebSocket Gateway with Redis Pub/Sub
- WebSocket Gateway maintains persistent connections with clients.
- On connection, client subscribes to symbols: {“subscribe”: [“AAPL”, “TSLA”]}.
- Gateway subscribes to Redis channels: quotes:AAPL, quotes:TSLA.
- Data Processing Layer publishes to Redis channels.
- Gateway receives updates and forwards to subscribed clients.
Scaling WebSocket Gateways:
- Run multiple gateway instances behind Layer 4 load balancer.
- Use sticky sessions or consistent hashing to route reconnections to same instance.
- Each gateway handles 50K-100K connections (depends on update frequency).
- Monitor connection churn and scale horizontally.
Option 2: Kafka-Based Fan-Out
- Data Processing Layer publishes to Kafka topics partitioned by symbol.
- WebSocket Gateways are Kafka consumers in a consumer group.
- Each gateway consumes from assigned partitions and maintains WebSocket connections.
- Clients are mapped to gateways based on symbol subscriptions.
Optimization: Tiered Pricing
Not all users need the same data freshness:
- Free Tier: 1-second delayed quotes (satisfies regulations for “delayed” data).
- Instant Tier: Real-time quotes with < 500ms latency.
- Professional Tier: Level 2 data (order book depth), sub-100ms latency.
This reduces load on real-time infrastructure and monetizes premium data.
Monitoring:
- Track end-to-end latency: exchange timestamp → client receipt.
- Monitor data gaps and missing symbols.
- Alert on quote staleness (no update in X seconds during market hours).
Deep Dive 2: How do we execute orders reliably with smart order routing and best execution?
Order execution is the most critical path in a trading system. Regulations require “best execution” - routing orders to venues that provide the best price.
Challenge:
- Orders must be routed to optimal venues (market centers, dark pools, market makers).
- Must comply with Reg NMS (National Market System) rules.
- Handle partial fills, rejections, and timeouts.
- Provide execution quality reports to users and regulators.
Solution: Smart Order Routing (SOR) Engine
Step 1: Pre-Trade Validation
Before routing, validate the order by checking several conditions. First, verify market hours - if the market is closed and the order doesn’t have extended hours time-in-force, throw an error. Next, check buying power by estimating the cost (quantity times market price) and comparing against available buying power. Validate position limits to ensure adding this quantity won’t exceed maximum position size. Finally, check Pattern Day Trader rules - if the account is flagged as PDT and has less than $25,000, reject orders that would create a fourth day trade within five business days.
Step 2: Routing Decision
Determine where to send the order by first getting the NBBO (National Best Bid and Offer). Consider various venues like NYSE, NASDAQ, IEX, and market makers like Citadel, each with their own bid/ask prices and fee structures. For buy orders, find the venue with the best ask price (lowest price plus fees). For sell orders, find the venue with the best bid price (highest price minus fees). For market orders, route to the venue with the best price. For limit orders, the order may be split across multiple venues to achieve best execution.
Considerations:
- Payment for Order Flow (PFOF): Market makers pay brokers to route retail orders to them. Controversial but common. Citadel Securities provides price improvement in exchange.
- Dark Pools: Private exchanges where institutions trade large blocks. May offer better prices with less market impact.
- Reg NMS: Orders must be routed to venues displaying the best price (NBBO). Can’t route to worse price even if receiving PFOF.
Step 3: FIX Protocol Execution
Send order to chosen venue via FIX (Financial Information eXchange) protocol. The FIX message includes msgType as “NewOrderSingle” (FIX message type ‘D’), a unique clOrdID generated for this order, the symbol, side as “1” for buy or “2” for sell, orderQty for quantity, ordType as “1” for market or “2” for limit, optional price field for limit orders only, timeInForce as “0” for day or “1” for GTC, and the current transactTime. The FIX gateway sends this message to the broker.
Step 4: Execution Reports
Broker responds with execution reports:
- Acknowledgment: Order accepted (FIX ExecutionReport with ExecType=“0”).
- Fill: Order executed (FIX ExecutionReport with ExecType=“F”).
- Partial Fill: Only part of order filled (FIX ExecutionReport with ExecType=“1”).
- Reject: Order rejected (FIX ExecutionReport with ExecType=“8”).
- Cancel: Order cancelled (FIX ExecutionReport with ExecType=“4”).
When handling execution reports, the system retrieves the order using the clOrdID and processes based on the execution type. For acknowledgments, update the order status to “accepted”. For fills, create a Trade record with orderId, symbol, quantity from lastQty, price from lastPx, timestamp from transactTime, and venue from exchange. Update the order status to “filled” with filledQuantity from cumQty and avgFillPrice from avgPx. Update the position by adding the filled quantity to the user’s holdings. Update the account balance by debiting or crediting the trade amount. Finally, send a notification to the user. For rejections, update the order status to “rejected” with the reject reason from the report text field and notify the user.
Handling Partial Fills:
Limit orders may fill in multiple parts. For example, an order to buy 100 shares at $182.50 might execute as: Fill 1 with 40 shares at $182.48, Fill 2 with 30 shares at $182.49, and Fill 3 with 30 shares at $182.50, for a total of 100 shares at an average price of $182.49. Each partial fill generates a Trade record. The order remains in “partially_filled” status until complete.
Order States:
Orders progress through states: pending → accepted → (optionally multiple partially_filled states) → filled. Orders can also transition from pending to rejected or cancelled.
Idempotency:
Execution reports may be received multiple times due to network retries. The system checks if a trade with the given execID already exists. If it does, skip processing to avoid duplicates. Otherwise, save the new trade record. This ensures idempotent handling of execution reports.
Deep Dive 3: How do we calculate portfolio valuations in real-time for millions of users?
Portfolio valuation seems straightforward (sum of positions × prices), but at scale with real-time requirements, it becomes complex.
Challenge:
- 5M active users, each with 5-10 positions on average = 25-50M positions.
- Prices update constantly (every second during market hours).
- Users expect instant portfolio updates when opening app or when prices change.
- Must also calculate unrealized gains, day change, diversification metrics.
Solution: Multi-Level Caching with Incremental Updates
Level 1: Position Cache
Store each user’s positions in Redis for fast access using a key like positions:{accountId}. The value is an array of position objects, each containing symbol, quantity (can be fractional), costBasis, and avgCost (average cost per share).
Level 2: Price Cache
Store latest prices in Redis (updated by Market Data Service) using keys like price:{symbol}. The value contains the current price and timestamp of the last update.
Level 3: Portfolio Cache
Store computed portfolio snapshots with short TTL using keys like portfolio:{accountId}. The value includes accountValue, the full positions array with enriched data, dayChange, dayChangePercent, and timestamp. Set a TTL of 1 second to balance freshness with performance.
Calculation Flow:
When calculating a portfolio for an account, first check the cache using the key portfolio:{accountId}. If the cached value exists and its timestamp is less than 1 second old, return it immediately. Otherwise, perform a cache miss calculation: retrieve positions from Redis using positions:{accountId}, get the account details to access cash balance, then iterate through each position. For each position, fetch the current price from Redis using price:{symbol}, calculate market value as quantity times current price, calculate unrealized gain as market value minus cost basis, and calculate unrealized gain percent as (unrealized gain / cost basis) times 100. Add each enriched position to the array and add its market value to the total portfolio value. After processing all positions, retrieve the previous close portfolio value to calculate day change as current total value minus previous close value, and day change percent as (day change / previous close) times 100. Finally, cache this portfolio object with a 1-second TTL and return it to the client.
Real-Time Push Updates:
Instead of polling, push updates to clients when prices change:
- Market Data Service publishes price updates to Kafka.
- Portfolio Update Service consumes price updates.
- For each price update, service identifies users with positions in that symbol by maintaining a reverse index in Redis: a key like symbol:holders:AAPL maps to a set of account IDs that hold that symbol.
- For each affected account, recalculate the portfolio (or just update the specific position).
- Push the update to users via WebSocket.
Optimization: Batch Processing
During high volatility, prices update very frequently. Instead of recalculating for every price tick:
- Batch price updates (e.g., process every 500ms).
- Conflate multiple updates for same symbol.
- Use worker pools to parallelize calculations.
Consistency Consideration:
Portfolio calculation is eventually consistent. A user might see their position as 10 shares of AAPL at a price that’s 1 second old, showing a value of $1825.20. This is acceptable for display purposes. Critical operations (placing orders) query real-time data directly.
Deep Dive 4: How do we implement fractional shares without regulatory and accounting nightmares?
Fractional shares are a key differentiator for Robinhood, but they introduce significant complexity.
Challenge:
- US exchanges only trade whole shares. You can’t buy 0.5 shares on NYSE.
- How do we offer fractional shares to users while only trading whole shares?
- How do we handle dividends, corporate actions (splits, mergers), and voting rights for fractional shares?
- How do we maintain accurate cost basis for tax reporting?
Solution: Fractional Share Pooling
Architecture:
- User View: Users see fractional shares in their accounts.
- Clearing Firm View: Robinhood holds whole shares in a “house account” or omnibus account.
- Internal Ledger: Robinhood maintains an internal ledger allocating fractional ownership to users.
Example:
Consider three users buying fractional shares of AAPL at $200/share: User A wants $100 worth (0.5 shares), User B wants $150 worth (0.75 shares), and User C wants $50 worth (0.25 shares), for a total of 1.5 shares. Robinhood’s process works as follows: Accept fractional orders throughout the day. Aggregate the totals: 0.5 + 0.75 + 0.25 = 1.5 shares needed. At specific times (e.g., market open), place a bulk order for 2 whole shares (round up to ensure sufficient inventory). After execution at $201/share (the actual market price), allocate proportionally to users: User A receives 0.5 shares at $201 costing $100.50, User B receives 0.75 shares at $201 costing $150.75, User C receives 0.25 shares at $201 costing $50.25. The remaining 0.5 shares stay in house inventory for future orders.
Database Schema:
The system maintains three key tables. The positions table stores user-facing positions with columns for account_id, symbol, quantity as a decimal supporting up to 6 decimal places for fractional shares, cost_basis, and avg_cost, with a primary key on (account_id, symbol). The house_inventory table tracks whole shares held by Robinhood with columns for symbol, quantity (also supporting fractional precision), and last_updated timestamp, with symbol as the primary key. The fractional_allocations table provides an audit trail with columns for allocation_id, bulk_order_id linking to the whole share order, account_id, symbol, allocated_quantity, allocated_price with 4 decimal precision, and timestamp.
Handling Dividends:
When AAPL pays a $0.50 per share dividend, Robinhood receives the dividend for all whole shares in the house account, then allocates proportionally to fractional shareholders. User A with 0.5 shares receives $0.25, User B with 0.75 shares receives $0.375, and User C with 0.25 shares receives $0.125. These amounts are credited to user cash accounts.
Handling Stock Splits:
When AAPL does a 4-for-1 split, Robinhood receives 4× shares in the house account and updates the internal ledger accordingly. User A’s 0.5 shares become 2.0 shares, User B’s 0.75 shares become 3.0 shares, and User C’s 0.25 shares become 1.0 shares. The cost basis is adjusted proportionally (divided by 4) to reflect the split.
Regulatory Compliance:
- SEC Rule 15c3-3 (Customer Protection Rule): Requires brokers to maintain physical possession or control of customer securities. Fractional shares held in house account must be segregated and accounted for.
- FINRA Rule 4370: Requires timely and accurate reporting of customer positions.
- Tax Reporting (Form 1099-B): Must accurately report cost basis for fractional share sales, including wash sales.
Challenges:
- Rounding Errors: With millions of users and fractional quantities, rounding errors accumulate. Use high-precision decimals and periodic reconciliation.
- Selling Restrictions: Users can only sell fractional shares back to Robinhood (not on open market). This introduces liquidity risk for Robinhood.
- Voting Rights: Fractional shareholders typically don’t get voting rights (only whole share holders vote).
Deep Dive 5: How do we implement margin trading with real-time risk management?
Margin trading allows users to borrow money to amplify returns, but it also introduces significant risk.
Challenge:
- Must comply with Regulation T (Federal Reserve Board): initial margin requirement of 50%.
- FINRA rules require maintenance margin of 25% (or higher for volatile stocks).
- Need real-time monitoring to detect margin calls.
- Must automatically liquidate positions if user doesn’t meet margin call.
Solution: Multi-Tiered Risk Management System
Tier 1: Pre-Trade Risk Checks
Before accepting any order, verify margin requirements. Get the account equity by adding cash balance and total position value. For buy orders, calculate the required margin as quantity times price times 0.5 (Reg T requirement). Calculate available margin as equity minus current margin used. If available margin is less than required margin, throw an “Insufficient margin” error. For sell orders, check if the position would result in a short sale. If selling more shares than currently held, calculate the short quantity and required margin as short quantity times price times 1.5 (150% requirement for short sales). If equity is less than the required margin, throw an error.
Tier 2: Real-Time Monitoring
Continuously monitor all margin accounts by retrieving all accounts with margin enabled and iterating through each one. For each account, calculate equity as cash balance plus total position value, and sum up the current margin used. Calculate maintenance margin requirement as 25% of total position value. For volatile stocks with annualized volatility exceeding 50%, add an extra 10% margin requirement to the maintenance margin. Check if equity is below maintenance margin plus margin used, and if so, trigger a margin call for the deficit amount. Check if the account is severely under-margined (equity below 80% of maintenance margin threshold), and if so, trigger immediate auto-liquidation.
Run this monitoring continuously during market hours (every 5-10 seconds) as prices update.
Tier 3: Margin Call Process
When margin call is triggered:
- Notification: Send immediate notifications via push, email, and SMS.
- Grace Period: Give user 2-5 days to either deposit more cash, sell positions to reduce margin usage, or close margin positions.
- Display Warning: Show prominent warning in app with details: amount needed to meet margin call, deadline, and consequences of non-compliance.
- Escalation: If user doesn’t respond, begin auto-liquidation.
Tier 4: Automatic Liquidation
If user doesn’t meet margin call by deadline or equity falls below critical threshold, the system retrieves all positions and sorts them by liquidity in descending order (easier to sell first). Calculate the margin deficit. For each position in order, if the deficit is covered, stop. Otherwise, calculate how much quantity to sell as the minimum of the full position quantity or the deficit divided by the price, multiplied by 1.2 to provide a 20% buffer. Place a market order to sell with highest priority using time-in-force as “ioc” (immediate or cancel), marking the reason as “margin_liquidation”. Subtract the sold value from the margin deficit. Log the liquidation for compliance and send a notification to the user that positions were liquidated due to margin call.
Risk Parameters:
Different stocks have different margin requirements. Large-cap stocks in the S&P 500 require 50% initial margin and 25% maintenance margin. Small-cap stocks require 50% initial margin and 30% maintenance margin. Volatile stocks (like meme stocks) require 100% initial margin and 50% maintenance margin, effectively doubling the requirements. Penny stocks priced under $5 require 100% margin for both initial and maintenance, meaning no margin is allowed.
During the GameStop squeeze, Robinhood raised margin requirements to 100% for GME, AMC, and similar stocks, effectively disabling margin trading for those securities.
Pattern Day Trader (PDT) Rules:
FINRA defines a day trade as buying and selling the same security within the same trading day. A Pattern Day Trader is anyone who executes 4 or more day trades within 5 business days. If flagged as PDT, the account must maintain $25K minimum equity. PDT accounts get 4× buying power (instead of 2×) but only for day trading purposes.
When checking for PDT violations, first determine if an order would result in a day trade by checking if the user already holds a position in the symbol that was acquired today and the order is a sell. If so, count the day trades in the last 5 days. If there are already 3 day trades and this would be the 4th, check if account equity is at least $25,000. If not, throw a “Pattern Day Trader rule violation” error requiring the user to maintain $25K minimum. If the equity is sufficient, flag the account as PDT to enable enhanced monitoring.
Deep Dive 6: How do we ensure compliance and maintain audit trails?
Regulatory compliance is non-negotiable for brokerages. SEC and FINRA require extensive record-keeping.
Required Records:
- Order Tickets: Every order with timestamp (microsecond precision), price, quantity, account.
- Execution Reports: Every trade with execution venue, price, timestamp.
- Account Ledgers: Every cash movement, dividend, fee.
- Compliance Actions: Margin calls, liquidations, restrictions.
- Customer Communications: Confirmations, statements, disclosures.
Audit Trail Design:
Use event sourcing pattern with an audit_events table. The table has columns for event_id as primary key, event_type describing the action, account_id, entity_type (order, trade, account, position), entity_id, event_data as JSONB for flexible storage, timestamp, user_id, and ip_address. Create indexes on (account_id, timestamp) and (entity_type, entity_id) for efficient querying.
Every action generates an immutable audit event. For example, when an order is placed, create an event with a unique event_id, event_type as “order_placed”, the relevant account_id, entity_type as “order”, entity_id pointing to the order ID, event_data containing the full order details (symbol, side, quantity, orderType, limitPrice, status), timestamp with microsecond precision, user_id of who placed the order, and ip_address of the client.
Regulatory Reports:
- Order Audit Trail System (OATS): Report all orders to FINRA within seconds (being replaced by CAT - Consolidated Audit Trail).
- Rule 606: Quarterly reports on order routing practices.
- Rule 607: Monthly statements to customers.
- Form 10-Q / 10-K: Quarterly and annual financial reports to SEC.
Data Retention:
SEC Rule 17a-4 requires retaining order records, trade confirmations, account statements, and compliance records for 6 years. Customer communications must be retained for 3 years. Use WORM (Write Once Read Many) storage or append-only databases. Options include S3 with Object Lock or specialized compliance storage solutions.
Monitoring and Alerts:
Monitor for suspicious activity including potential insider trading, wash sales, large or unusual orders, frequent account funding and withdrawals (potential money laundering), high-frequency trading patterns, and violations of trading restrictions. All anomalies should trigger alerts for compliance review.
Step 4: Wrap Up
In this chapter, we designed a comprehensive stock trading platform like Robinhood. If there is extra time at the end of the interview, here are additional points to discuss:
Additional Features:
- Options Trading: Multi-leg strategies (spreads, straddles, iron condors), complex risk calculations.
- Cryptocurrency Trading: 24/7 trading, different settlement (instant vs. T+2), integration with crypto exchanges.
- Recurring Investments: Auto-invest on schedule with dollar-cost averaging.
- Dividend Reinvestment: Automatically reinvest dividends to buy more shares.
- Tax-Loss Harvesting: Automatically sell losing positions to offset capital gains.
- IPO Access: Allow retail investors to participate in IPOs (traditionally institutional only).
- Social Features: See what stocks friends are buying, discussion forums.
Scaling Considerations:
- Geographic Expansion: Each country has different regulations (MiFID II in EU, FCA in UK).
- Multi-Asset Classes: Expand to bonds, futures, forex, commodities.
- Institutional Clients: Serve hedge funds, asset managers with higher volume and different needs.
- Database Sharding: Shard by account ID for user data, by symbol for market data.
- Read Replicas: Use read replicas for portfolio queries, reports, analytics.
Error Handling:
- Exchange Outages: If NYSE goes down, route to alternative exchanges (NASDAQ, IEX).
- Clearing Firm Issues: Have backup clearing relationships.
- Data Feed Failures: Fallback to alternative data vendors.
- Network Partitions: Handle split-brain scenarios with distributed consensus.
- Rogue Trades: Circuit breakers to prevent fat-finger errors (e.g., selling 1M shares instead of 1K).
Security Considerations:
- DDoS Protection: CloudFlare, AWS Shield to prevent service disruption.
- Authentication: MFA (multi-factor authentication) required for all users.
- Authorization: Role-based access control (RBAC) for internal users.
- Encryption: TLS for data in transit, AES-256 for data at rest.
- PCI DSS Compliance: For handling payment card information (deposits/withdrawals).
- Penetration Testing: Regular security audits and bug bounty programs.
Monitoring and Analytics:
- Trade Execution Quality: Track fill rates, price improvement, execution speed.
- System Health: Monitor latency, throughput, error rates, API response times.
- Business Metrics: Daily active users, trade volume, revenue, customer acquisition cost.
- Anomaly Detection: Detect unusual trading patterns, system behavior.
- Real-Time Dashboards: Operations team needs visibility into system health during market hours.
Disaster Recovery:
- Multi-Region Deployment: Active-active or active-passive across AWS regions.
- Database Replication: Synchronous replication for critical data (account balances, positions).
- Backup Clearing: Have agreements with multiple clearing firms.
- Incident Response: Runbooks for common failures, on-call rotations.
- Testing: Regular DR drills, chaos engineering to test resilience.
Cost Optimization:
- Revenue Streams: Payment for order flow, margin interest, premium subscriptions (Robinhood Gold), interest on cash balances.
- Cost Centers: Market data subscriptions (expensive), clearing fees, cloud infrastructure, compliance/legal.
- Unit Economics: Cost per trade, cost per user, lifetime value.
Future Improvements:
- Algorithmic Trading: Allow users to create custom trading algorithms.
- AI-Powered Insights: Personalized stock recommendations, risk analysis.
- Advanced Charting: Technical analysis tools, backtesting capabilities.
- Mobile-First Innovation: Voice trading (“Alexa, buy 10 shares of Apple”), biometric authentication.
- Gamification: Achievements, leaderboards (careful with regulatory implications).
Congratulations on getting this far! Designing Robinhood is one of the most complex system design challenges, touching on real-time data streaming, financial transactions, regulatory compliance, risk management, and massive scale. The key is to understand both the technical architecture and the business/regulatory context in which it operates.
Summary
This comprehensive guide covered the design of a stock trading platform like Robinhood, including:
-
Real-Time Market Data: Multi-tier streaming architecture with feed handlers, data processing pipelines, and WebSocket distribution to millions of users with sub-second latency.
-
Order Execution: Smart order routing with FIX protocol integration, pre-trade validation, execution quality optimization, and handling of multiple order types (market, limit, stop-loss).
-
Portfolio Management: Real-time portfolio valuation with multi-level caching, incremental updates, and efficient handling of millions of positions.
-
Fractional Shares: Internal pooling and allocation system to offer fractional ownership while trading whole shares externally.
-
Margin Trading: Comprehensive risk management with real-time monitoring, margin call process, and automatic liquidation to comply with Regulation T and FINRA rules.
-
Compliance: Event sourcing for audit trails, regulatory reporting (OATS, Rule 606), data retention, and suspicious activity monitoring.
The design demonstrates how to build a production-grade financial system that balances user experience, regulatory compliance, system reliability, and business sustainability.
Comments