Files
supabase/apps/reference/docs/guides/realtime/postgres-cdc.mdx

125 lines
3.8 KiB
Plaintext

---
id: postgres-cdc
title: Postgres CDC
description: Getting started with Realtime's Postgres CDC feature
---
Realtime's Postgres Change Data Capture (CDC) feature listens for database changes and sends them to clients. Clients are required to subscribe with a JWT dictating which changes they are allowed to receive based on the database's [Row Level Security](/docs/guides/auth/row-level-security).
Anyone with access to a valid JWT signed with the project's JWT secret is able to listen to your database's changes, unless tables have [Row Level Security](/docs/guides/auth/row-level-security) enabled and policies in place.
Clients can choose to receive `INSERT`, `UPDATE`, `DELETE`, or `*` (all) changes for all changes in a schema, a table in a schema, or a column's value in a table. Your clients should only listen to tables in the `public` schema and you must first enable the tables you want your clients to listen to.
Postgres CDC works out of the box for tables in the `public` schema. You can listen to tables in your private schemas by granting table `SELECT` permissions to the database role found in your access token. You can run a query similar to the following:
```sql
GRANT SELECT ON "private_schema"."table" TO authenticated;
```
:::caution
We strongly encourage you to enable RLS and create policies for tables in private schemas. Otherwise, any role you grant access to will have unfettered read access to the table.
:::
You can do this in the [Replication](https://app.supabase.com/project/_/database/replication) section in the Dashboard or with the [SQL editor](https://app.supabase.com/project/_/sql):
```sql
begin;
-- remove the supabase_realtime publication
drop publication if exists supabase_realtime;
-- re-create the supabase_realtime publication with no tables
create publication supabase_realtime;
commit;
-- add a table to the publication
alter publication supabase_realtime add table messages;
```
By default, only `new` record changes are sent but if you want to receive the `old` record (previous values) whenever you `UPDATE` or `DELETE` a record,
you can set the `replica identity` of your table to `full`:
```sql
alter table messages replica identity full;
```
To listen to all changes in the `public` schema:
```js
const { createClient } = require('@supabase/supabase-js')
const supabase = createClient(
process.env.SUPABASE_URL,
process.env.SUPABASE_KEY
)
/*
Channel name can be any string.
Event name can can be one of:
- INSERT
- UPDATE
- DELETE
- *
*/
const channel = supabase
.channel('schema-db-changes')
.on('postgres_changes', { event: '*', schema: 'public' }, (payload) =>
console.log(payload)
)
.subscribe()
```
To listen to changes on a table in the `public` schema:
```js
// Supabase client setup
const channel = supabase
.channel('table-db-changes')
.on(
'postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'messages' },
(payload) => console.log(payload)
)
.subscribe()
```
To listen to changes when a column's value in a table matches a client-specified value:
```js
// Supabase client setup
const channel = supabase
.channel('value-db-changes')
.on(
'postgres_changes',
{
event: 'UPDATE',
schema: 'public',
table: 'messages',
filter: 'body=eq.hey',
},
(payload) => console.log(payload)
)
.subscribe()
```
To listen to different events and schema/tables/filters combinations with the same channel:
```js
// Supabase client setup
const channel = supabase
.channel('db-changes')
.on(
'postgres_changes',
{ event: '*', schema: 'public', table: 'messages', filter: 'body=eq.bye' },
(payload) => console.log(payload)
)
.on(
'postgres_changes',
{ event: 'INSERT', schema: 'public', table: 'users' },
(payload) => console.log(payload)
)
.subscribe()
```