SysPad › Examples › Nearby friends
Nearby friends
Periodic pings over WebSocket fan out via per-user Redis Pub/Sub channels to ~40 online friends each, so delivery runs 40x the ping rate back onto the same socket tier (a Return edge closes the loop); the latest location lives only in a TTL cache and history is written off the hot path.
Fan-out amplification as the real load: 6k pings/s become 240k deliveries/s landing back on the ONE socket fleet that sent them - a drawn loop the Return edge keeps out of the topology math while the delivery flow carries its load.
- Throughput: 6,350 req/sec
- First to saturate: Nothing at this load
- Estimated cost: $16k/mo
How it works
- NLB
- L4, not L7: WebSocket connections are long-lived and stateful, so you balance once at connect time. Three AZs so a zone loss only drops a third of the sockets (clients reconnect).
- WebSocket Servers
- One fleet, two jobs: it receives pings AND, as the subscriber to friends’ channels, delivers their updates down open sockets - which is why it is sized for ~40x its ingest rate. Self-hosted rather than API Gateway WebSocket: the managed quota (10k msg/s) and per-message pricing do not survive this fan-out. Stateful, so deploys need connection draining.
- HTTP API Service
- The stateless request/response half (auth, profile, friend management). Kept apart from the socket tier so ordinary CRUD never competes with the real-time path.
- Location Cache
- The latest location per user, with a ~10 minute TTL - deliberately the ONLY store of current position. Losing it is acceptable: the next ping repairs it. Most of its load is subscriber distance checks, not pings.
- Location History
- Cassandra-style append trail of pings for analytics and ML, written fire-and-forget. Durability lives here precisely so the real-time path never has to wait for it.
- Location Pub/Sub
- One channel per user; your ~40 online friends subscribe to yours. Each ping is written once and read ~40 times, which is why this node is sized for ops fan-out, and why channels are sharded by user id across a pub/sub cluster. The dashed Return edge back to the socket tier is the delivery leg: real, but never re-triggering.
- Friends Cache
- Who your friends are, cached: read on every connect to build the subscription set and the initial nearby list. Backed by the user DB on a miss.
Request flows
Share my location
- Client
- NLB
- WebSocket Servers
- Location Cache
- Location History
- Location Pub/Sub
Receive friends' updates
- Location Pub/Sub
- WebSocket Servers
- Location Cache
Open the app
- Client
- NLB
- WebSocket Servers
- Friends Cache
- User & Friends DB
- Location Cache
Add or remove a friend
- Client
- NLB
- HTTP API Service
- User & Friends DB
- Friends Cache