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 rather than 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. - The password position holds a placeholder, so type in your own password.
Use the session pooler
Supabase now hands out direct connections over IPv6 only. Plenty of networks cannot route that, and the failure shows up as a hostname that will not resolve. The session pooler answers on IPv4 and behaves like an ordinary Postgres connection, which is what Rig wants. Take the pooler on port 5432 rather than the transaction pooler on 6543.
Connect it in Rig
Adding a source needs a workspace owner, or a role with the Manage connections permission, on a workspace where you manage your own connections. If the Connectors tab says “Data ingestion for this workspace is managed by Rig”, ask an owner or Rig support to add the source.
- In Rig, open
Connections, choose theConnectorstab and go toSources & actions. - Search for Supabase, open the card named Supabase and click
Connect. The PostgreSQL / Supabase card is a separate connector. - 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
Continue. Rig connects with those details and lists every table in the schema, largest first, with all of them ticked. Untick any you do not want and clickConnect. - The source then syncs on its schedule, which is nightly unless you change it. To load data straight away, click
Syncon its row;Testpulls a small sample first if you want to check the connection.
What Rig pulls in
The tables you left ticked, one warehouse table per source table, with column types carried across rather than flattened to text. A table added to the schema later is not picked up on its own. To bring it in, click the icon on the source's row whose tooltip reads “Edit which streams sync”. In the Edit streams dialog, tick the new table and click Save allowlist.
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 rather than 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 applies to a read-only role too. Postgres enforces RLS on every role that does not own the table and does not have
BYPASSRLS, so on a table with RLS switched on and no policy for Rig's role, Rig reads zero rows without an error. Either give the roleBYPASSRLS, or add aSELECTpolicy for it on each table you want synced. - 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
publiconly, which leaves outauthandstorage. If you want a second schema, add a second connection pointed at it withAdd another connectionon the Supabase card. The form then asks for an Account label, such as the schema's name.
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
postgresfollowed 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. If the grants are in place and tables still come back empty, row level security is filtering every row out, as described above. - 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