Presence
Get up and running with Realtime's Presence feature
Presence can be used to share state between clients. Each client maintains their own piece of state within the shared state.
Presence utilizes an in-memory conflict-free replicated data type (CRDT) to track and synchronize shared state in an eventually consistent manner. It computes the difference between existing state and new state changes and sends the necessary updates to clients via Broadcast.
When a new client subscribes to a channel, it will immediately receive the channel's latest state in a single message instead of waiting for all other clients to send their individual states.
Clients are free to come-and-go as they please, and as long as they are all subscribed to the same channel then they will all have the same Presence state as each other.
The neat thing about Presence is that if a client is suddenly disconnected (for example, they go offline), their state will be automatically removed from the shared state. If you've ever tried to build an “I'm online” feature which handles unexpected disconnects, you'll appreciate how useful this is.
Quick start#
Let's explore how to implement Realtime Presence so you can integrate it into your use case.
Install the client
Install the Supabase JavaScript client.
_10 npm install @supabase/supabase-js
Create the first client
This client will be used to track Presence state as new clients join and leave the channel.
Go to your Supabase project's API Settings and grab the URL
and anon
public API key.
_10 import {_10 createClient_10 } from '@supabase/supabase-js'_10_10 const clientA = createClient(_10 'https://<project>.supabase.co',_10 '<your-anon-key>'_10 )
Create a channel
A channel's topic can be anything except for 'realtime'
.
_10 const channelA = clientA.channel('room-1')
Sync and track state
Listen to the sync
, join
, and leave
events triggered whenever any client joins or leaves the channel or changes their slice of state.
To begin tracking state, clientA
calls channelA.track()
, passing in the desired state to share. Once clientA
successfully tracks its state, it will automatically trigger its own sync
and join
event handlers.
_32 channelA_32 .on(_32 'presence',_32 { event: 'sync' },_32 () => {_32 const newState = channelA.presenceState()_32 console.log('sync', newState)_32 }_32 )_32 .on(_32 'presence',_32 { event: 'join' },_32 ({ key, newPresences }) => {_32 console.log('join', key, newPresences)_32 }_32 )_32 .on(_32 'presence',_32 { event: 'leave' },_32 ({ key, leftPresences }) => {_32 console.log('leave', key, leftPresences)_32 }_32 )_32 .subscribe(async (status) => {_32 if (status === 'SUBSCRIBED') {_32 const presenceTrackStatus = await channelA.track({_32 user: 'user-1',_32 online_at: new Date().toISOString(),_32 })_32 console.log(presenceTrackStatus)_32 }_32 })
Create the second client
This client will add to and remove from shared state so other clients can be notified of changes to Presence state.
_10 const clientB = createClient(_10 'https://<project>.supabase.co',_10 '<your-anon-key>'_10 )
Create another channel
This channel's topic must match channelA
's.
_10 const channelB = clientB.channel('room-1')
Add to state
Subscribe to channel and add to state.
This will trigger clientA
's sync
and join
event handlers.
_10 channelB.subscribe(async (status) => {_10 if (status === 'SUBSCRIBED') {_10 const presenceTrackStatus = await channelA.track({_10 user: 'user-2',_10 online_at: new Date().toISOString(),_10 })_10 console.log(presenceTrackStatus)_10 }_10 })
Remove from state
This will trigger clientA
's sync
and leave
event handlers.
_10 const untrackPresence = async () => {_10 const presenceUntrackStatus = await channelB.untrack()_10 console.log(presenceUntrackStatus)_10 }_10_10 untrackPresence()
Presence Key#
By default, Presence will generate a unique UUIDv1
key on the server to track a client channel's state. If you prefer, you can provide a custom key when creating the channel. This key should be unique among clients.
_10import { createClient } from '@supabase/supabase-js'_10_10const channelC = supabase.channel('test', {_10 config: {_10 presence: {_10 key: 'userId-123',_10 },_10 },_10})
Client-Side Rate Limit#
By default the client will rate limit itself at 10 messages per second (1 message every 100 milliseconds). You can customize this when creating the client:
_10import { createClient } from '@supabase/supabase-js'_10_10const supabase = createClient('https://<project>.supabase.co', '<your-anon-key>', {_10 realtime: {_10 params: {_10 eventsPerSecond: 5,_10 },_10 },_10})
By setting eventsPerSecond
to 5, you can send one message every 200 milliseconds on a per client basis.
Learn more by visiting the Quotas section.