Home

Presence

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.

Presence State#

You can get started by listening to sync event messages notifying the client that a channel's state has been synchronized on the server. You can get the state by calling the channel's presenceState helper:


_12
const { createClient } = require('@supabase/supabase-js')
_12
_12
const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY)
_12
_12
const channel = supabase.channel('test')
_12
_12
channel
_12
.on('presence', { event: 'sync' }, () => {
_12
const state = channel.presenceState()
_12
console.log(state)
_12
})
_12
.subscribe()

Whenever there's Presence activity on the 'test' channel, this sync event will be broadcast to all clients subscribed to the channel.

Listen to Joins#

You can create a client and listen to new state joining the channel's Presence:


_10
// Supabase client setup
_10
_10
const channel = supabase.channel('test')
_10
_10
channel
_10
.on('presence', { event: 'join' }, ({ key, newPresences }) => {
_10
console.log(key, newPresences)
_10
})
_10
.subscribe()

Track Presence#

On another client, subscribe to the channel and insert state to be tracked by Presence:


_13
// Supabase client setup
_13
_13
const channel = supabase.channel('test')
_13
_13
channel.subscribe(async (status) => {
_13
if (status === 'SUBSCRIBED') {
_13
const presenceTrackStatus = await channel.track({
_13
user: 'user-1',
_13
online_at: new Date().toISOString(),
_13
})
_13
console.log(presenceTrackStatus)
_13
}
_13
})

Presence Key#

By default, Presence will generate an UUIDv1 key on the server to uniquely track a client channel's state but you may pass Presence a custom key when creating the channel.


_19
// Supabase client setup
_19
_19
const channel = supabase.channel('test', {
_19
config: {
_19
presence: {
_19
key: 'userId-1',
_19
},
_19
},
_19
})
_19
_19
channel.subscribe(async (status) => {
_19
if (status === 'SUBSCRIBED') {
_19
const presenceTrackStatus = await channel.track({
_19
user: 'user-1',
_19
online_at: new Date().toISOString(),
_19
})
_19
console.log(presenceTrackStatus)
_19
}
_19
})

Listen to Leaves#

You can create a client and listen to a client channel's state leaving:


_10
// Supabase client setup
_10
_10
const channel = supabase.channel('test')
_10
_10
channel
_10
.on('presence', { event: 'leave' }, ({ key, leftPresences }) => {
_10
console.log(key, leftPresences)
_10
})
_10
.subscribe()

Untrack Presence#

On another client, subscribe to the channel, and remove tracked state from Presence:


_17
// Supabase client setup
_17
_17
const channel = supabase.channel('test')
_17
_17
channel.subscribe(async (status) => {
_17
if (status === 'SUBSCRIBED') {
_17
const presenceTrackStatus = await channel.track({
_17
user: 'user-1',
_17
online_at: new Date().toISOString(),
_17
})
_17
_17
if (presenceTrackStatus === 'ok') {
_17
const presenceUntrackStatus = await channel.untrack()
_17
console.log(presenceUntrackStatus)
_17
}
_17
}
_17
})

Client-Side Rate Limit#

There is a default client-side rate limit that enables you to send 10 messages per second, or one message every 100 milliseconds. You can customize this when creating the client:


_12
const { createClient } = require('@supabase/supabase-js')
_12
_12
const supabase = createClient(
_12
process.env.SUPABASE_URL,
_12
process.env.SUPABASE_KEY,
_12
{
_12
realtime: {
_12
params: {
_12
eventsPerSecond: 5
_12
}
_12
}
_12
}

By setting eventsPerSecond to 5, you can send one message every 200 milliseconds on a per client basis.

Learn more by visiting the Rate Limits section.