SysDesignPrep.com
Interactive concepts

Online presence at scale with heartbeats, grace periods and fan-out: an interactive simulator

Showing who is online looks like a single boolean per user, but it is a failure detector and a fan-out problem at once. The server only knows a client is there while heartbeats arrive, mobile connections drop for seconds at a time, and every change of status is a message to everyone watching. The heartbeat interval, a grace period before announcing that someone left, and who receives updates decide how accurate presence is and what it costs.

The playground follows one phone for half an hour: ten short connection drops, then the user leaves at 25 minutes. Change the settings and compare what friends are shown with what really happened.

Heartbeat everyGrace periodUpdates go to

Over half an hour the connection drops 10 times, for 2 to 50 seconds. With a heartbeat every 5 s, the server decides the user is gone after 10 s of silence. Friends saw them drop offline 5 times although they never left, for 4, 29, 10, 43 and 16 s, and every flicker is two broadcasts. At 25 minutes the phone loses signal for good, and friends keep seeing the user online for another 9 s. Across 10M online users that is 2M heartbeats a second and 4M presence updates a second to the 60 online friends.

False offlines5shown although the user never left
Online after leaving9 sthe phone lost signal
Heartbeats2M/sfor 10M online users
Presence updates4M/s12 changes per session, 60 recipients each
connected, or shown onlineconnection droppedshown offline by mistakeshown online after leavinguser leaves

What the settings trade

  • A fast heartbeat notices a real departure quickly, here 9 s after the phone lost signal, but it also notices every tunnel and elevator: friends saw this user go offline 5 times although they never left, and each flicker is two broadcasts. At 10 million online users, a 5 s heartbeat is 2 million writes a second to the presence store.
  • A slow heartbeat hides every short drop and cuts heartbeats to 167K a second, but the user who really left is shown online for 1 min 44 s.
  • A grace period before announcing offline filters flickers without making the heartbeat slower. With a 5 s heartbeat and 30 s of grace, only the 50 s drop shows, at the cost of a 39 s delay on a real departure.
  • A goodbye message on a clean close makes the delay irrelevant for most departures: the app tells the server it is leaving and friends see it at once. The heartbeat timeout only has to catch crashes and lost signal, so it can be generous.
  • The audience multiplies everything. Sending each change to all 200 friends costs 25 times as much as sending it to the 8 who have the user on screen; most systems push only to subscribers of a visible conversation or contact list and let everyone else read presence when they open a screen.

A typical design

# gateway, on every heartbeat (or any message) from a connected client
SET presence:812 "online" EX 30           # key expires unless refreshed

# key expired: wait out the grace period, then publish once
if not reconnected within grace:
    PUBLISH presence-changes {user: 812, status: offline, last_seen: t}

# clean close: the client says goodbye, no waiting
DEL presence:812; PUBLISH presence-changes {user: 812, status: offline}

# fan-out: only to clients that subscribed to 812 because it is on their screen
for conn in subscribers["812"]: conn.send({user: 812, status: offline})

Gateways hold the long-lived connections and refresh a key with a TTL in a store such as Redis on each heartbeat. A key that expires after the grace period produces one change event, published on a channel partitioned by user, and the gateways forward it only to their connections subscribed to that user. Large group chats often show a count of members online, or presence only for the people visible on screen.

In a system design interview

When a chat or social design shows online status, say how it is detected and who hears about it: “Clients heartbeat every 30 seconds over the WebSocket; the gateway refreshes a presence key with a TTL. We announce offline only after a grace period, so tunnels do not flicker, and a clean close sends an explicit goodbye. Updates go only to clients subscribed to that user because it is on their screen, and we show ‘last seen’ rather than live presence in very large groups.” Expect the follow-ups: the write rate of heartbeats, users connected on several devices, and fan-out for users with huge followings.

Read the guide to presence and connection management or WebSockets vs SSE vs long polling, see heartbeat failure detection, or watch a strong candidate design WhatsApp.

Questions people ask

How do chat apps know if a user is online?

The client keeps a long-lived connection, usually a WebSocket, and sends a heartbeat every few seconds to tens of seconds. The server refreshes a presence record with a time to live on each heartbeat; when heartbeats stop and the record expires, the user is considered offline.

How often should a client send heartbeats?

Often enough to detect a lost connection within the delay the product accepts, but no more: each heartbeat is a write at the presence store, so a 5 second interval for 10 million users is 2 million writes a second. Intervals of 15 to 60 seconds are common, combined with an explicit goodbye on clean disconnects.

Why does a user flicker between online and offline?

Mobile connections drop briefly in tunnels, elevators and network handovers. If the server announces offline as soon as the heartbeat timeout passes, every longer drop becomes an offline and online pair of updates. A grace period before announcing offline hides drops that end quickly.

What is a grace period in presence systems?

A delay after the server decides a connection is gone and before it tells anyone. If the client reconnects within it, nothing is broadcast. It filters flicker without a slower heartbeat, at the cost of showing a user who really left as online for a little longer.

How do you scale presence fan-out?

Send updates only to clients that need them now, typically the users whose screens show this person, instead of every friend or member. Others read presence when they open a screen. Very large groups show a count online or last seen times instead of live status for every member.

How is presence handled for users on several devices?

Each device has its own connection and heartbeat, and the user is online if any device is. The presence store keeps a set of active connections per user, and an offline event is published only when the last one goes away.

What is last seen?

A timestamp of the user’s last activity, stored when they disconnect or periodically while active. It is cheaper than live presence because nobody has to be told when it changes; readers fetch it when they open a chat.