0) Problem Restatement
Design a real-time location sharing system similar to WhatsApp Live Location. Users should be able to share their live coordinates with individuals or groups for a fixed duration. Key challenges include maintaining low-latency updates (< 2s) for millions of concurrent users while optimizing for mobile battery consumption and gps accuracy.
1) Requirements
1.1 Functional
- Share Live Location: Real-time sharing with 1:1 contacts or groups.
- Stop Sharing: Manual override to stop sharing at any time.
- Auto-Expiry: Sharing automatically ends after a chosen duration (15m, 1h, 8h).
- Real-time Map: View others' moving locations on a map interface.
1.2 Non-Functional
- Low Latency: Updates must reach friends in near real-time (< 2–3s delay).
- High Scalability: Support millions of concurrent sharers and viewers.
- Reliability: System should be fault-tolerant; server restarts shouldn't drop active sessions.
- Battery Efficiency: Minimize mobile resource usage (GPS/Network).
1.3 Scale Estimates
- Daily Active Users (DAU): 50 million.
- Concurrent Live Shares: 2 million.
- Update Frequency: Every 5 seconds per user.
- Total Writes: ~400,000 requests/sec.
- Storage: Temporary in-memory storage for active sessions; no long-term archival needed for core functionality.
1.4 API Design
The core APIs required for the service:
- Start Sharing:
POST /v1/sessions/start- Initialize a live sharing session. - Update Location:
POST /v1/location/update- Client pushes latest lat/lon. - Get Friends Locations:
GET /v1/sessions/active- Sync current locations of sharing friends. - Stop Sharing:
POST /v1/sessions/stop- Immediately end an active session.
2) High-Level Architecture
2.1 Overview
- Location Service (Write Path): Receives and validates incoming updates, persisting them to a fast in-memory store.
- Pub/Sub Layer: Fan-out service using Redis/Kafka to push updates to all authorized subscribers.
- WebSocket Service: Maintains persistent connections with viewing clients for low-latency delivery.
2.2 Architecture Diagram
Architecture Diagram
flowchart TB
U1["Sharer (Mobile App)"] -->|"1. Start/Update"| AG["API Gateway"]
AG -->|"2. Validate"| LS["Location Service"]
LS -->|"3. Write with TTL"| Redis[(Redis / In-Memory Store)]
LS -->|"4. Notify Hub"| PS["Pub/Sub (Kafka/Redis)"]
PS -->|"5. Fan-out"| WS["WebSocket Service"]
WS -->|"6. Push Update"| U2["Friend (Mobile App)"]
classDef sharer fill:#f0faff,stroke:#0077be,stroke-width:1px;
classDef viewer fill:#f0fff4,stroke:#228b22,stroke-width:1px;
classDef core fill:#fff5f5,stroke:#dc3545,stroke-width:1px;
class U1 sharer;
class U2 viewer;
class LS,WS,Redis,PS,AG core;3) Components Breakdown
3.1 Client (Mobile App)
- Adaptive GPS polling based on user activity.
- Efficient batching of location data where possible.
- Persistent WebSocket connection for background updates.
3.2 Fan-out: Who Is Watching Whom
- Session record:
share:{session_id}→ sharer, allowed viewers,expires_at. Written on start; its TTL is the share duration. - Latest location:
loc:{session_id}→ lat, lon, accuracy, timestamp (overwritten on every update, same TTL). - Connection registry:
conn:{user_id}→ which WebSocket server holds that user's connection (set on connect, cleared on disconnect, short TTL refreshed by heartbeats). - Delivery: On each update, the Location Service publishes to channel
session:{session_id}. WebSocket servers subscribe to the channels of sessions their connected viewers are watching (subscribe when a viewer opens the chat/map, unsubscribe when they leave), and push to those sockets. - Viewer opens the map late: read
loc:{session_id}once for the current position, then receive live updates.
3.3 Storage Strategy
- Redis TTL: Use session expiry as the TTL (Time-To-Live) for location keys.
- In-Memory Speed: Essential for the 400k+ writes/sec requirement.
- Automatic Cleanup: Redis automatically removes expired session data.
4) Scale Considerations
- Sharding: Partition Redis by
session_idto distribute load. - Fan-out Handling: Fan-out is small by nature — a share goes to one contact or one group (at most a few hundred members), so Redis Pub/Sub per session is enough. There is no "celebrity" case to design for.
- Connection Routing: A WebSocket stays on one server for its lifetime; what matters is the connection registry (which server holds which user) so updates reach the right server, and reconnecting clients resubscribe wherever they land.
- Geo-Filtering: Only push updates to friends who are actually looking at the map for the specific user.
5) Deep Dive Candidate Topics
- Adaptive Precision: Reducing GPS frequency when a user is stationary to save battery.
- Message Delivery Guarantees: Tradeoffs between at-most-once (fast) vs at-least-once (reliable) delivery for live positions.
- Handling Sudden Disconnects: Implementing graceful handovers for mobile network switching.
6) Tradeoffs & Extensions
- Why Redis TTL vs SQL cleanup jobs? → simplicity, auto-expiry.
- Why WebSocket vs Push Notifications? → low latency vs intermittent.
- Extensions: could add geo-fencing (notify when friend enters area).