Home

Realtime Presence Quickstart

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.

1

Install the client

Install the Supabase JavaScript client.


_10
npm install @supabase/supabase-js

2

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
)

3

Create a channel

A channel's topic can be anything except for 'realtime'.


_10
const channelA = clientA.channel('room-1')

4

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
})

5

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
)

6

Create another channel

This channel's topic must match channelA's.


_10
const channelB = clientB.channel('room-1')

7

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
})

8

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.


_10
import { createClient } from '@supabase/supabase-js'
_10
_10
const 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:


_10
import { createClient } from '@supabase/supabase-js'
_10
_10
const 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.

More Realtime Quickstarts#