Connect Supabase to Rig
Your product database is usually the one place where what a customer actually did is recorded rather than reported. Mirroring it into the warehouse puts signups, usage and billing rows next to the CRM and the support queue, so a question about churn can reach the behaviour behind it instead of stopping at the summary.
- Requirements
- The database password for your Supabase project
- Time required
- 5 mins
Before you start
The password is the one thing Supabase will not show you again
Four of the five values Rig needs are printed on the connection screen. The database password is not one of them. Supabase displays it once, when the project is created, and after that the only option is to reset it in Project settings, then Database. Resetting is safe, but it breaks every other client using the old password, so find out whether someone already has it before you change it.
- A Supabase login with access to the project you want to mirror.
- The database password for that project, or the authority to reset it.
Find your connection details
- Log in to Supabase and select the right project.
- Click
Connectat the top of the project. - Choose Session pooler, not the direct connection.
- Read the four values out of the connection string. It has the shape
postgresql://USERNAME:PASSWORD@HOST:PORT/DATABASE, so the host, port, database name and username are all sitting in front of you. - Note that the password position is a placeholder, not your password. That is the value you supply yourself.
Use the session pooler, not the direct connection
Supabase now hands out direct connections over IPv6 only. Plenty of networks cannot route that, and the failure looks like a hostname that will not resolve rather than anything to do with credentials. The session pooler answers on IPv4 and behaves like an ordinary Postgres connection, which is what Rig wants. Take the pooler on port 5432, not the transaction pooler on 6543.
Connect it in Rig
- In Rig, open
Connectionsand go toSources & actions. - Search for Supabase and open the card.
- Dialect: leave it on
postgresql. - Host and Port: from the pooler string, so a
pooler.supabase.comhost on port5432. - Database name and Username: also from the string. The username carries your project reference after a dot, and that dot matters.
- Password: the project database password.
- Schema to ingest: leave it as
public, which is prefilled and is where Supabase puts your application tables. - Click
Test, thenSync.
What Rig pulls in
Every table in the schema, one warehouse table per source table, with column types carried across rather than flattened to text. This is a mirror, not a selection: you do not pick tables up front, and a table added to the schema later arrives on the next sync without anyone reconfiguring anything.
After the first run, Rig tries to sync each table incrementally rather than reloading it. It looks for a timestamp column to use as a cursor and takes the first one it finds, in this order:
updated_atmodified_atcreated_atinserted_at
updated_at comes first on purpose. A cursor on created_at only ever catches new rows, so a row that changes after it was written never gets re-read and your copy quietly drifts from the source.
All of that depends on the table having a primary key, which is the part worth knowing in advance. Rig only syncs a table incrementally if it can merge on a key, so a table without one is replaced in full every run no matter which timestamp columns it has. A table with a key but no recognised timestamp is also reloaded each sync, which is correct but heavier.
JSON and JSONB columns land as text, not as a native JSON type. Rig serialises them on the way in and pins the warehouse column to text deliberately, because otherwise the loader re-parses the value and the load breaks. Parse them at query time on the warehouse side.
Good to know
- Give Rig its own read-only role rather than the postgres superuser. Rig only ever reads, so a role with
SELECTon the schema is enough, and it means you can revoke Rig's access on its own without resetting the password every other client is using. Worth the five minutes if the project is production. - Row level security does not apply to this connection. RLS is enforced for the anon and authenticated roles your app uses, not for a direct Postgres login. Rig sees the table as the role you give it sees the table, so scope the grants rather than relying on policies.
- Tables extract one at a time, sharing a single connection pool, so a wide schema takes longer than it would in parallel but cannot exhaust the database or the memory on the sync worker. The first run is the slow one.
- Supabase's own internal schemas are not included. You are ingesting
public, notauthorstorage. If you want a second schema, add a second connection pointed at it.
Troubleshooting
- The host will not resolve: you have taken the direct connection string rather than the session pooler. Go back to
Connectand switch tabs. The pooler host haspooler.supabase.comin it. - Authentication fails but the password is right: check the username. On the pooler it is not plain
postgres, it ispostgresfollowed by a dot and your project reference, and dropping that suffix is the usual cause. - Nothing syncs and there is no error: the role can connect but cannot read. Grant
USAGEon the schema andSELECTon its tables. - A table reloads in full every night: most often it has no primary key, and Rig only syncs incrementally what it can merge on a key. Adding a timestamp column will not change that on its own. Give the table a primary key, and add an
updated_atmaintained by a trigger if it has no recognised timestamp either, and it turns incremental on the following sync. - Row counts drift from the source: the table is cursored on
created_atbecause it has noupdated_at, so edits and soft deletes after insert are never re-read. This is the case the cursor order above is warning about. - A JSON column will not destructure: it arrived as text, which is deliberate. Cast or parse it in the warehouse rather than expecting a native JSON type.
What people use this for
- Analyse product data without touching production
- Join product behaviour to revenue and support
- Give AI tools real product context