mirror of
https://github.com/supabase/supabase.git
synced 2026-07-03 22:54:19 +08:00
125 lines
3.8 KiB
Plaintext
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()
|
|
```
|