Realtime

Migrate to Broadcast Changes

How to migrate from Postgres Changes to Broadcast Changes


Postgres Changes has some limitations as your application scales. To continue broadcasting database changes to users as you scale, you can use Broadcast Changes.

Example application using Postgres Changes

Here we have a simple chess application that has a game id and we want to track whenever we have new moves happening for a given game id.

We store this information in a public.moves table and every time a new move is added to a given game_id we want to receive the changes in our connected Realtime client

In our client we will have our implementation to receive insert events with the usual code:


_15
const gameId = '4a8bbe89-f601-4414-bd47-8d0f7ab2a31a'
_15
const changes = supabase
_15
.channel('chess-moves')
_15
.on(
_15
'postgres_changes',
_15
{
_15
event: 'INSERT',
_15
schema: 'public',
_15
table: 'moves',
_15
filter: `game_id=eq.${gameId}`,
_15
},
_15
(payload) => console.log(payload)
_15
)
_15
.subscribe()
_15
...

Migrate to broadcast changes

To use Broadcast Changes, first familiarize yourself with the Broadcast Changes implementation.

Set up authorization

Broadcast Changes is private by default, using Realtime Authorization to control access. First, set up RLS policies to control user access to relevant messages:


_13
CREATE POLICY "authenticated can listen to game moves"
_13
ON "realtime"."messages"
_13
FOR SELECT
_13
TO authenticated
_13
USING (
_13
EXISTS (
_13
SELECT 1
_13
FROM game_users
_13
WHERE (SELECT auth.uid()) = user_id
_13
AND (select realtime.topic()) = 'games:' || game_id::text
_13
AND realtime.messages.extension = 'broadcast'
_13
)
_13
);

Set up trigger function

We need to define our trigger function to adapt to our use case and use the provided function realtime.broadcast_changes


_14
CREATE OR REPLACE FUNCTION public.broadcast_moves() RETURNS trigger AS $$
_14
BEGIN
_14
PERFORM realtime.broadcast_changes(
_14
'games:' || NEW.game_id::text, -- topic
_14
TG_OP, -- event
_14
TG_OP, -- operation
_14
TG_TABLE_NAME, -- table
_14
TG_TABLE_SCHEMA, -- schema
_14
NEW, -- new record
_14
OLD -- old record
_14
);
_14
RETURN NULL;
_14
END;
_14
$$ LANGUAGE plpgsql;

Setup trigger with created function

Now we need to setup our trigger to capture the events we want


_10
CREATE TRIGGER chess_move_changes
_10
AFTER INSERT ON public.moves
_10
FOR EACH ROW
_10
EXECUTE FUNCTION public.broadcast_moves();

Listen to changes in client

Finally you can setup your client to listen for your events


_12
const gameId = '4a8bbe89-f601-4414-bd47-8d0f7ab2a31a'
_12
await supabase.realtime.setAuth() // Needed for Realtime Authorization
_12
const changes = supabase
_12
.channel(`games:${gameId}`)
_12
.on(
_12
'broadcast',
_12
{
_12
event: 'INSERT',
_12
},
_12
(payload) => console.log(payload)
_12
)
_12
.subscribe()