Location Sharing Service: Low Level Design
Data Model
Location Table (Time-Series)
Location
--------
device_id BIGINT
lat DOUBLE PRECISION
lng DOUBLE PRECISION
accuracy_meters FLOAT
heading FLOAT -- degrees 0-360
speed FLOAT -- m/s
timestamp TIMESTAMPTZ
PRIMARY KEY (device_id, timestamp)
PARTITION BY RANGE (timestamp) -- one partition per day
Raw location rows are retained for 24 hours, then dropped with the partition. The last-known location for each device is maintained separately in Redis for instant retrieval.
Share Session Table
ShareSession
------------
id BIGINT PK
owner_device_id BIGINT
share_code VARCHAR(8) UNIQUE -- random token, e.g. "aB3xQr7Z"
permission ENUM('realtime','last-known')
expires_at TIMESTAMPTZ
max_viewers INT
created_at TIMESTAMPTZ
revoked_at TIMESTAMPTZ
Live Location Updates
Ingestion API
POST /locations
Authorization: Bearer {device_token}
{
"lat": 37.7749,
"lng": -122.4194,
"accuracy_meters": 5.0,
"heading": 270.0,
"speed": 12.5,
"timestamp": "2024-01-01T12:00:00Z"
}
Devices POST every 5 seconds while moving, or every 30 seconds while stationary (battery optimization via adaptive frequency — determined client-side using accelerometer data).
On receipt:
- Write row to
Locationtable. - Update Redis key
lastloc:{device_id}with the new coordinates (TTL: 7 days). - PUBLISH to Redis channel
share:{share_code}for all active share sessions owned by this device.
Watcher Registry and WebSocket Fan-Out
Watcher Registry
Redis Set key: watchers:{share_code}
Members: {node_id}:{connection_id}
TTL: reset on each WebSocket heartbeat
When a viewer opens a WebSocket connection using a share code, their connection ID is added to the set. Multiple app server nodes each subscribe to the Redis Pub/Sub channel for every active share code they serve.
Fan-Out Flow
Device POST /locations
│
▼
Write to DB + update Redis lastloc
│
▼
PUBLISH to Redis channel "share:{share_code}"
│
├──▶ Node A receives → pushes to connected WebSocket clients
└──▶ Node B receives → pushes to connected WebSocket clients
Privacy and Access Control
- Share code: random 8-character alphanumeric token; not guessable. Shared out-of-band (SMS, link).
- Permission levels:
realtimestreams live updates;last-knownreturns a single snapshot. - Expiry: sessions have an
expires_at; expired sessions reject new WebSocket connections. - Revocation: owner calls
DELETE /share/{share_code}→ setsrevoked_at, closes all active WebSocket connections for that code, removes Redis set. - Viewer cap:
max_viewersenforced at WebSocket handshake time via set cardinality check.
REST API Summary
POST /locations -- ingest location update
POST /share -- create share session → returns share_code
GET /share/{share_code}/location -- get last-known location (HTTP)
WS /share/{share_code}/live -- real-time WebSocket stream
DELETE /share/{share_code} -- revoke share session
Scalability Notes
- Redis Pub/Sub fan-out decouples ingestion from delivery; any node can serve any viewer.
- Time-series partitioning keeps the hot partition small; old partitions are dropped cheaply.
- WebSocket nodes are stateless beyond the in-memory connection map; horizontal scaling is straightforward.
- For very high fan-out (live event sharing with thousands of viewers), Redis Streams with consumer groups can replace simple Pub/Sub.
See also: Uber Interview Guide 2026: Dispatch Systems, Geospatial Algorithms, and Marketplace Engineering
See also: Snap Interview Guide