STANDARDwalkthrough

Presence Service

3 of 8
3 related
How do we show green dots for 500M online users without melting the pub/sub layer? The naive approach broadcasts every status change to every contact.
At 500M users coming online over 10 minutes during morning peak, that is 500M×500/600=417M500M \times 500 / 600 = 417M presence events per second, which overwhelms any pub/sub system. We chose lazy presence (not eager broadcast): we store each user's status in Redis with a key presence:user_id, value = status, last_seen, server_id, and a 60-second TTL.
A user with 500 contacts going online triggers 500 push notifications.
The client sends a heartbeat every 30 seconds to refresh the TTL. If the heartbeat stops (app closed, network lost), the key expires and the user is implicitly offline.
We only push presence changes to users who are actively viewing a chat with that contact. When User A opens a conversation with User B, the client subscribes to B's presence channel.
When B's status changes, only subscribers get notified, not all 500 contacts. Why not store presence in the database?
Because presence is ephemeral: it changes every time a user opens or closes the app. Writing 16.7M heartbeats/sec to MySQL would saturate the write pipeline.
Redis handles this with in-memory writes and auto-expiry via TTL. Trade-off: presence accuracy has a 30-60 second lag (heartbeat interval + TTL), but users tolerate 'last seen 1 minute ago' over perfectly real-time status.
Why it matters in interviews
The presence broadcast storm is the classic interview trap. Candidates who eagerly push status to all contacts cannot explain how it scales. Showing the math (417M417M events/sec) and solving it with lazy presence plus subscriber-only push demonstrates you think about fan-out costs before coding.
Related concepts