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:
_12const { createClient } = require('@supabase/supabase-js')_12_12const supabase = createClient(process.env.SUPABASE_URL, process.env.SUPABASE_KEY)_12_12const channel = supabase.channel('test')_12_12channel_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_10const channel = supabase.channel('test')_10_10channel_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_13const channel = supabase.channel('test')_13_13channel.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_19const channel = supabase.channel('test', {_19 config: {_19 presence: {_19 key: 'userId-1',_19 },_19 },_19})_19_19channel.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_10const channel = supabase.channel('test')_10_10channel_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_17const channel = supabase.channel('test')_17_17channel.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:
_12const { createClient } = require('@supabase/supabase-js')_12_12const 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 Quotas section.