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

    1. Log in to Supabase and select the right project.
    2. Click Connect at the top of the project.
    3. Choose Session pooler rather than the direct connection.
    4. 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.
    5. 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.

    1. In Rig, open Connections, choose the Connectors tab and go to Sources & actions.
    2. Search for Supabase, open the card named Supabase and click Connect. The PostgreSQL / Supabase card is a separate connector.
    3. Dialect: leave it on postgresql.
    4. Host and Port: from the pooler string, so a pooler.supabase.com host on port 5432.
    5. Database name and Username: also from the string. The username carries your project reference after a dot, and that dot matters.
    6. Password: the project database password.
    7. Schema to ingest: leave it as public, which is prefilled and is where Supabase puts your application tables.
    8. 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 click Connect.
    9. The source then syncs on its schedule, which is nightly unless you change it. To load data straight away, click Sync on its row; Test pulls 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_at
    • modified_at
    • created_at
    • inserted_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 SELECT on 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 role BYPASSRLS, or add a SELECT policy 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 public only, which leaves out auth and storage. If you want a second schema, add a second connection pointed at it with Add another connection on 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 Connect and switch tabs. The pooler host has pooler.supabase.com in it.
    • Authentication fails but the password is right: check the username. On the pooler it is postgres followed 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 USAGE on the schema and SELECT on 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_at maintained 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_at because it has no updated_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

    More ideas for using Supabase

    Was this guide helpful?