SysPadExamples › 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.

Client Users NLB NLB WebSocket Servers Fargate HTTP API Service Fargate Location Cache ElastiCache Location History Keyspaces Location Pub/Sub Redis Stream Friends Cache ElastiCache User & Friends DB Aurora

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

  1. Client
  2. NLB
  3. WebSocket Servers
  4. Location Cache
  5. Location History
  6. Location Pub/Sub

Receive friends' updates

  1. Location Pub/Sub
  2. WebSocket Servers
  3. Location Cache

Open the app

  1. Client
  2. NLB
  3. WebSocket Servers
  4. Friends Cache
  5. User & Friends DB
  6. Location Cache

Add or remove a friend

  1. Client
  2. NLB
  3. HTTP API Service
  4. User & Friends DB
  5. Friends Cache

Other interview practice

Open this architecture in SysPad · All examples