Presence shows whether a user is online, away, or offline right
now. Use it for the green "online" dot next to a name, or "Agent is away"
in a support chat.
Where this fits: your app is connected to a conversation (see the
Chat quickstart). Presence works automatically: being
connected makes you online. You only call setPresence to show away.
Presence is different from membership. Members are who may chat in a conversation. Presence is who is here right now.
Use it
In your app:
chat.on('presence', (event) => {
console.log(`${event.userId} is ${event.status}`);
});
await chat.setPresence('away');
const present = await chat.getPresence();
// [{ userId: 'bob', status: 'online' }]const presence = usePresence(); // { [userId]: status }, kept in syncThis hook only reads. To change your own status, call
useChatClient()?.setPresence(status).
livqeno.chat!.on('presence', (event) => console.log(`${event.userId} is ${event.status}`));
await livqeno.chat!.setPresence('away');chat.presence.listen((entry) => print('${entry.userId} is ${entry.status}'));
await chat.setPresence(LivqenoPresenceStatus.away);
final present = await chat.getPresence();A typical pattern:
- When the chat opens, call
getPresence()to draw the initial dots. - Listen for
presenceevents to update them. - When the user switches to another tab or app, call
setPresence('away'). When they come back, callsetPresence('online').
How presence works
| Fact | Value |
|---|---|
| Saved to the database? | No. It's short-lived on purpose. |
| How long it lasts | 45 seconds, unless refreshed |
| How often it's refreshed | Every 20 seconds, while connected |
Presence changes all the time, like when a user switches tabs. Saving every change would cost a lot and be useless seconds later.
How a user goes offline
- Clean disconnect (user leaves normally): they go offline right away.
- Crash, closed laptop, lost network: nothing tells the server. Their presence simply expires, so they go offline within 45 seconds.
This means users never get stuck as "online" forever.
Only changes are sent
The 20-second refresh does not send an event. You only get a presence
event when a status actually changes. This keeps busy rooms quiet.
Multiple tabs
Presence is per user, not per tab. Three open tabs show as one online.
Closing one tab doesn't make the user offline.
Large rooms
In a room with more than 200 people online (the default threshold, such as
a live stream's chat), sending a presence event for every arrival would
flood everyone. Instead:
- per-user
presenceevents stop; - every client gets a
presenceCountevent,{ roomId, online }, at most every 5 seconds and only when the number changed (plus one last count when the room drops back under the threshold); - the full list is paged with
listPresence()(at most 200 per page).
chat.on('presenceCount', ({ roomId, online }) => setViewerCount(online));
let page = await chat.listPresence({ limit: 200 });
while (page.nextCursor) {
page = await chat.listPresence({ cursor: page.nextCursor, limit: 200 });
}const online = usePresenceCount(); // works in small rooms and large oneschat.presenceCounts.listen((count) => setState(() => viewers = count.online));
final page = await chat.listPresence(limit: 200);getPresence() still works, but in a large room it returns only the first
page.
Live-stream audience viewers
Viewers of a live stream's chat join with an audience token: the token
names the one conversation they may join (the SDK joins it by itself if you
don't pass room), and they can read and post without being members.
chat.isAudienceViewer is true for these clients. Member-only features —
the inbox, read receipts and push — don't apply to viewers,
and their calls reject with NOT_A_MEMBER without reaching the server.
Slow mode, mutes, bans and the moderation hook still apply.
Common mistakes
| Mistake | What you'll see | Fix |
|---|---|---|
| Expecting offline instantly after a crash | The user shows online for up to 45 seconds. | This is expected. See above. |
| Using presence to decide who can read | Offline members still get messages later from history. | Use Members for access. Presence is display only. |
Next steps
- Typing Indicators: the other "who's here" signal.
- Delivery & Read Receipts