DEVELOPERS.md
| Language | Source | Package |
|---|---|---|
| JavaScript | supabase-js/realtime-js | @supabase/realtime-js |
| Flutter/Dart | supabase-flutter/realtime_client | realtime_client |
| Python | supabase-py/realtime | realtime |
| Swift | supabase-swift/Realtime | supabase-swift |
Pre-requisites:
Optional but recommended:
To run the server locally, start the Postgres databases based on supabase/postgres that contains all plugins and config required by Realtime:
mise run db-start
With the database running, setup deps and start the server:
mix setup
mise run dev
To start another node in the local cluster (optional):
mise run dev-orange
Once the server is up, open http://localhost:4000/status to check the services are running.
Note To run the whole stack in containers instead of installing Elixir locally:
mise run realtime-start
Useful cleanup commands:
mise run db-rm
mise run realtime-rm
To see all available tasks:
mise task ls
A tenant has already been added on your behalf. You can confirm this by checking the _realtime.tenants and _realtime.extensions tables inside the database.
Note Supabase runs Realtime in production with a separate database that keeps track of all tenants. For local development, the compose setup creates the
_realtimeschema for you.
You can add your own by making a POST request to the server. You must change both name and external_id while you may update other values as you see fit:
curl -X POST \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiIiLCJpYXQiOjE2NzEyMzc4NzMsImV4cCI6MTcwMjc3Mzk5MywiYXVkIjoiIiwic3ViIjoiIn0._ARixa2KFUVsKBf3UGR90qKLCpGjxhKcXY4akVbmeNQ' \
-d $'{
"tenant" : {
"name": "realtime-dev",
"external_id": "realtime-dev",
"jwt_secret": "a1d99c8b-91b6-47b2-8f3c-aa7d9a9ad20f",
"extensions": [
{
"type": "postgres_cdc_rls",
"settings": {
"db_name": "postgres",
"db_host": "host.docker.internal",
"db_user": "postgres",
"db_password": "postgres",
"db_port": "5432",
"region": "us-west-1",
"poll_interval_ms": 100,
"poll_max_record_bytes": 1048576,
"ssl_enforced": false
}
}
]
}
}' \
http://localhost:4000/api/tenants
Note The
Authorizationtoken is signed with the secret set byAPI_JWT_SECRETin the local compose environment.
If you want to listen to Postgres changes, you can create a table and then add the table to the supabase_realtime publication:
create table test (
id serial primary key
);
alter publication supabase_realtime add table test;
You can start playing around with Broadcast, Presence, and Postgres Changes features either with the client libs (e.g. @supabase/realtime-js), or use the built in Realtime Inspector on localhost, http://localhost:4000/inspector/new (make sure the port is correct for your development environment).
The WebSocket URL must contain the subdomain, external_id of the tenant on the _realtime.tenants table, and the token must be signed with the jwt_secret that was inserted along with the tenant.
If you're using the default tenant, the URL is ws://realtime-dev.localhost:4000/socket (make sure the port is correct for your development environment), and you can use eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MDMwMjgwODcsInJvbGUiOiJwb3N0Z3JlcyJ9.tz_XJ89gd6bN8MBpCl7afvPrZiBH6RB65iA1FadPT3Y for the token. The token must have exp and role (database role) keys.
The WebSocket URL is in the following format for local development: ws://[external_id].localhost:4000/socket/websocket
If you're using Supabase's hosted Realtime in production the URL is wss://[project-ref].supabase.co/realtime/v1/websocket?apikey=[anon-token]&log_level=info&vsn=1.0.0"
WebSocket connections are authorized via symmetric JWT verification. Only supports JWTs signed with the following algorithms:
Verify JWT claims by setting JWT_CLAIM_VALIDATORS:
e.g. {'iss': 'Issuer', 'nbf': 1610078130}
Then JWT's "iss" value must equal "Issuer" and "nbf" value must equal 1610078130.
Note:
JWT expiration is checked automatically.
expandrole(database role) keys are mandatory.
Authorizing Client Connection: You can pass in the JWT by following the instructions under the Realtime client lib. For example, refer to the Usage section in the @supabase/realtime-js client library.