Labs

System lab · medium · 28 min

Discord: Online presence

Accurate online status for a huge user base without drowning in heartbeats.

Presence sounds like the easiest feature in a chat app. It's a green dot. But that dot has to be right for 100 million people, it changes every time someone closes a laptop lid, and every change has to reach everyone who can see it. In this lab you'll design a presence system from a blank page, modelled on a chat product like Discord's. You'll find that the hard part isn't storing the dot. It's telling people when it changes.

The brief

You're building the "who is online" layer for a chat product organised into servers (communities) and friend lists. Users open the app on a phone, a desktop app or a browser tab. Next to every name in a member list or friend list there is a status: online, idle, do not disturb, or offline. Some users also show an activity, like "Playing a game" or "Listening to a song".

People use presence to decide whether to message someone, whether to jump into a voice channel, and whether a community feels alive.

In scope for this lab:

  • Tracking whether each user is connected, across all their devices.
  • Showing status for friends and for members of the servers you're looking at.
  • Pushing changes to the people who should see them.
  • Custom status and current activity.

Out of scope:

  • Sending messages, voice and video. Assume a separate chat service exists.
  • Typing indicators. They use similar machinery but are even more short-lived.
  • Notifications to offline phones.

Requirements

Functional

  • When a user connects, they appear online to their friends and to the servers they belong to.
  • When a user disconnects or goes quiet, they appear offline (or idle) within a short time.
  • A user can set a status manually: online, idle, do not disturb, invisible.
  • A user can have an activity ("Playing X") that others can see.
  • A client opening a server's member list sees the current status of the visible members, and then sees changes live.
  • Invisible users appear offline to everyone else, but can still use the app.

Non-functional

  • Fresh: a status change should reach watchers within about 5 seconds in normal conditions. Going offline after a crash can take up to about 60 seconds.
  • Scalable fan-out: a server can have 1 million members. One person going online must not cost a million messages.
  • Cheap per update: presence changes far more often than messages do. It has to be the cheapest thing in the system.
  • Available, not exact: a wrong dot for a few seconds is fine. Presence being down should never stop people chatting.
  • Privacy: invisible must really look offline. No leaks through activity or "last seen" fields.

That fourth one matters a lot. Presence is a soft state system. It's allowed to be a little wrong, it rebuilds itself from live connections, and it never needs to survive a restart on disk. That frees you from almost every expensive tool you'd reach for with real data.