What is Presence (Online Status)?

Last updated: July 2026

Presence is a real-time signal of whether a user is currently online, away, or offline, kept fresh by connections and heartbeats. The green dot is deceptively simple UI over a genuinely hard distributed problem: the server must infer absence — devices rarely announce their death — and then broadcast every inference to everyone watching, at contact-list scale. Standardized long before modern chat, in XMPP’s presence stanzas, the pattern’s fundamentals haven’t changed since.

Key takeaways

QuestionAnswer
The statesonline · away/idle · offline — plus user-set overrides (do not disturb)
The mechanismHeartbeat writes + TTL expiry; connection events as the fast path
The numbers~30 s heartbeat · offline timeout at 2–3× the interval · 30–60 s flap grace
The companionLast seen — the durable timestamp behind the ephemeral dot
The hard partFan-out: N watchers × M status changes, multiplied by your success

The heartbeat contract

The entire pattern fits in one exchange:

client   every 30 s:  save { status: "online", lastActiveAt: now }
server   every 60 s:  sweep — lastActiveAt older than 90 s?  → status: "offline"
                      (TTL = 2–3 × heartbeat interval)
watcher  status = "online"   → green dot
         status = "offline"  → "last seen 12:41"  ← lastActiveAt, the durable part

The same contract as SDK code — heartbeat out, subscription in:

// JavaScript / Node.js — Back4app JS SDK
// Presence: heartbeat your own status, subscribe to your contacts'
const heartbeat = () =>
  myPresence.save({ status: 'online', lastActiveAt: new Date() });
await heartbeat();
setInterval(heartbeat, 30_000); // server sweeps offline at 2–3× this

const contacts = new Parse.Query('Presence');
contacts.containedIn('user', myContactIds);
const sub = await contacts.subscribe();
sub.on('update', (p) => setStatus(p.get('user'), p.get('status')));

Connection events vs. heartbeat TTL

The two detection models, compared honestly — no ranking page does this in one table:

Connection lifecycleHeartbeat + TTL
Online signalSocket openedFresh heartbeat within window
Offline signalClose event / close frameTTL expiry — no heartbeat for 2–3 intervals
Detection speedInstant on clean closeBounded delay (up to the timeout)
Silent failuresMissed — power loss sends no close frameCaught — silence is the signal
Server statePer-connection trackingStateless writes to a TTL store
Fails howZombie “online” usersBrief false “offline” on missed beats

The WebSocket protocol itself teaches the lesson: it ships ping/pong control frames precisely because TCP won’t reveal a vanished peer, and its close-code taxonomy reserves 1006 for “abnormal closure — no close frame received,” the zombie case. Production presence therefore layers both models: connection events for instant transitions, heartbeat expiry as the truth that catches what events miss.

The state machine

Presence state machine with grace periodA user moves from offline to online on connect or heartbeat, from online to away when the app is backgrounded or input goes idle, and toward offline through a grace period that starts on disconnect or missed heartbeats and is cancelled if the user reconnects before it elapses.

connect / heartbeat

tab hidden · input idle

activity resumes

disconnect or missed beats

disconnect or missed beats

reconnects in time

timer fires → publish

offline
(serve last seen)

online

away

grace period
30–60 s

A user moves from offline to online on connect or heartbeat, from online to away when the app is backgrounded or input goes idle, and toward offline through a grace period that starts on disconnect or missed heartbeats and is cancelled if the user reconnects before it elapses.

Two refinements distinguish polished implementations. Away is client-detected: the server can’t see a backgrounded tab, but the browser can — the Page Visibility API flags hidden tabs, input listeners flag idleness, and a best-effort offline signal on tab close rides the Beacon API. Offline is debounced: the grace state exists because mobile connections flap — publish “offline” on every tunnel and elevator, and every watcher’s contact list flickers in sympathy. Delay the announcement, cancel on reconnect, and flapping collapses into stillness. One more distinction worth stealing from the protocol that formalized presence: computed presence (online, by connection) versus user-set status (do not disturb) — the latter always wins the merge.

Ephemeral by design

Presence is a cache of reality, not a record: a status that arrives late is worse than none — yesterday’s “online” is a lie today. That principle drives the implementation choices: statuses live in fast stores with TTLs rather than durable tables, are never queued for offline delivery, and are the first data dropped under backpressure. Only lastActiveAt deserves persistence. Typing indicators are the principle at its extreme — micro-presence scoped to one conversation, expiring in seconds, debounced at the sender, and discarded rather than retried; if “Ada is typing…” can’t arrive now, it should never arrive.

The fan-out problem

Presence’s scaling wall is multiplication, not storage. A worked example: 100,000 concurrent users, each visible to 50 contacts, each transitioning state a modest 20 times per hour — that is 100,000 × 50 × 20 = 100 million presence events per hour to deliver, from a feature that stores one small row per user. The levers, in the order to pull them: subscribe narrowly — watch the users on screen (the open conversation list), not the full contact graph; pull, don’t push, the long tail — fetch last-seen when a profile opens instead of streaming it; cap broadcast in groups — beyond a few hundred members, show presence on interaction, not for the roster; and batch transitions so a flapping user costs one debounced event, not thirty. Fan-out itself rides the standard pub/sub machinery — presence is that pattern’s at-most-once corner case, where dropping a stale event is a feature.

Multi-device and privacy

One user, three devices, one dot — presence per user is a merge over presence per device. Track each device’s heartbeat separately; the user is online while any device is, and the merge policy is most-available-wins: online on the phone beats idle on the desktop, and any device’s do-not-disturb overrides the rest. Last-seen reports the most recent device. Privacy is the other half of the design, and the half engineering blogs skip despite being what users most ask about: visibility rules (everyone / contacts / nobody), reciprocity (hide yours, lose sight of others’), and coarse last-seen (“recently” instead of timestamps). Enforce the rules in the data layer’s permissions — presence is behavioral data, and a leaked “online at 3 a.m.” is a real disclosure.

Common use cases

  • Chat and messaging — the canonical green dot, last seen, and typing indicators.
  • Collaboration tools — who’s in the document, cursor presence, active-now sidebars.
  • Support and marketplaces — agent availability routing, “seller is online” trust signals.
  • Multiplayer and social — lobbies, friend lists, join-your-friend affordances.
  • Workforce tools — availability states feeding routing and status dashboards.

How should you build presence? A decision matrix

FeatureMechanism
Green dot on contactsHeartbeat + TTL store, live-query subscription on visible users
Instant transitions in an open chatConnection events as fast path over the socket
Last seenTimestamp on every heartbeat; pull on demand
Away detectionClient-side: visibility + idle listeners, reported in the heartbeat
Typing indicatorPer-conversation micro-events, seconds-long TTL, never persisted
Presence in a 5,000-member groupDon’t broadcast — show on interaction, cap the roster

Limitations and trade-offs

  • Presence is probabilistic. Between heartbeats, the dot is a guess; honest systems embrace bounded staleness rather than pretending to instant truth.
  • Freshness costs writes. Halving the heartbeat interval doubles write load across every online user — detection speed is purchased in throughput.
  • Fan-out scales with success. The feature is cheap at 1,000 users and an architecture project at 10 million; design the subscription scope before growth forces it.
  • Flapping is inherent. Mobile networks guarantee reconnect churn; without debouncing, presence amplifies network noise into UI noise.
  • It is surveillance-shaped. Online patterns reveal sleep, work, and habits; visibility controls and permission-layer enforcement are requirements, not enhancements.

Presence on Back4app

Back4app is an open-source Backend-as-a-Service (BaaS) platform that combines a managed database, auto-generated REST and GraphQL APIs, authentication, file storage, and Cloud Code serverless functions. The building blocks above map one-to-one: a Presence class holds status and lastActiveAt; the heartbeat is a periodic save (the code tabs); watchers hold a Live Query subscription on the contacts currently on screen, receiving pushed updates over the platform’s managed WebSocket fleet; a scheduled Cloud Code job is the TTL sweep, flipping stale rows to offline and firing the debounce; and class-level permissions plus ACLs implement the visibility rules in the data layer, where they belong. Nothing bespoke to operate — presence becomes a data-modeling exercise over infrastructure the backend already runs.

Frequently asked questions

What is a presence system?

A service that tracks whether each user is currently online, away, or offline and broadcasts changes to the users allowed to see them, in real time. Under the hood: persistent connections or periodic heartbeats writing to a fast in-memory store, with status changes fanned out over pub/sub.

How do apps know you are online?

Two signals, usually combined: the act of holding an open real-time connection (socket open means present), and periodic heartbeats sent over it. When heartbeats stop for longer than a timeout window — typically two to three intervals — the server marks you offline, even if the connection never formally closed.

How does "last seen" work?

The server records a timestamp on every heartbeat and disconnect. While you are online, the live status is served; once you go offline, the last recorded timestamp answers instead. It is the one durable piece of an otherwise ephemeral system — status expires, last-seen persists.

What heartbeat interval should presence use?

Thirty seconds is the common production default, with the offline timeout at two to three times the interval (60–90 seconds). Faster intervals shrink detection delay but multiply write load linearly with your online population; the interval must also stay below infrastructure idle timeouts, or proxies kill quiet connections first.

Connection-based or heartbeat-based detection — which is better?

Both, for different failures. Connection events (open/close) give instant transitions but miss silent deaths — a device that loses power sends no close frame, leaving a zombie connection. Heartbeat expiry bounds that staleness at the cost of detection delay. Production systems use connection events as the fast path and heartbeat TTL as the source of truth.

How do you stop online status from flickering?

Debounce the offline transition: on disconnect, start a grace timer — commonly 30 to 60 seconds — and cancel it if the user reconnects, publishing "offline" only when the timer fires. Users on elevators and train tunnels reconnect constantly; without the grace period, every contact list they appear on flickers with them.

How does presence scale to millions of users?

By respecting the fan-out math: every status change must reach every watcher, so N contacts times M transitions explodes fast. The levers are an in-memory TTL store for status, subscribing only to visible users (the open chat list, not the full contact book), pulling last-seen on demand instead of pushing it, and capping status broadcast in large groups.

How does multi-device presence work?

Track a connection or heartbeat per device and merge: the user is online while any device is, offline only when the last one goes quiet. The usual merge policy is most-available-wins — online on the phone beats idle on the desktop — with last-seen taken from the most recent device.

Can users hide their online status?

They should be able to — visibility is a product feature, not an afterthought: rules like everyone, contacts-only, or nobody, usually with reciprocity (hide yours and you cannot see others'). Presence data is behavioral data; scope who can watch whom in the permission model, not in the UI.

Related terms

Compare with

Further reading

Ready to build your backend?

Start your project on Back4app in minutes — database, auth, APIs, and Cloud Code included. No credit card required.

Written and reviewed by Back4app Engineering, Back4app Engineering · Published 2026-07-24