Connect your database
Create a read-only Postgres role for ParityRail, plus an optional narrow repair role.
ParityRail reads your app’s own record of who has access — usually your users table — so it can compare that to what Stripe says. Give it a Postgres login that can only read.
Before you start
- A Postgres (or Supabase) database reachable from ParityRail’s network — allowlist or firewall opened, and TLS reachable.
- Permission to run
CREATE ROLEandGRANT— a superuser connection, or the Supabase SQL editor. You will not hand this powerful credential to ParityRail. - The database name and host:port, for building the connection string.
- Admin role on the ParityRail project — connecting a database requires admin.
- Optional: to enable repairs, the ability to create a second, column-scoped role.
Connect your database
- Run the read-only role SQL against your database. Replace the password placeholder with a strong secret, and adjust the granted tables to the ones ParityRail will read — your users table, plus organizations and members if you bill teams.
CREATE ROLE parityrail_readonly WITH LOGIN PASSWORD '...'; GRANT CONNECT ON DATABASE app_db TO parityrail_readonly; GRANT USAGE ON SCHEMA public TO parityrail_readonly; GRANT SELECT ON public.users TO parityrail_readonly; GRANT SELECT ON public.organizations TO parityrail_readonly; GRANT SELECT ON public.organization_members TO parityrail_readonly; - Assemble a read-only connection string for that role:
postgres://parityrail_readonly:<password>@<your-db-host>:5432/<your-db-name> - In the ParityRail onboarding wizard, go to step 3 (Database) and stay on the “Postgres / Supabase” tab. Paste the string into the “Read-only connection string” field. The collapsible “How to create a read-only role” holds the same SQL with a copy button, if you need it again.
- Optional — to allow repairs, run the repair-role SQL:
CREATE ROLE parityrail_repair WITH LOGIN PASSWORD '...'; GRANT UPDATE (plan, is_premium, trial_ends_at) ON public.users TO parityrail_repair;Then assemble its connection string and paste it into the “Repair connection string (optional)” field:postgres://parityrail_repair:<password>@<your-db-host>:5432/<your-db-name>Leave this field empty to run detect-only. - Click “Test connection”. The button reads “Testing connection…” while ParityRail runs a
SELECT 1against the read-only URL, and against the repair URL too if you provided one.
6543 or the direct port 5432works, because ParityRail opens short-lived connections. Don’t reuse the anon or service_role roles.Verify it worked
On success, a toast reads “Database connected (<host>/<database>)” and the form is replaced by a green “Database connected” card showing <host> / <database>, plus · repair role configured when you supplied a repair string. Continue becomes enabled.
Troubleshooting
| Symptom | Fix |
|---|---|
Connection refused — check the host/port and that the database accepts remote connections. | Nothing is listening at that host:port, or remote connections are blocked (Postgres ECONNREFUSED). |
Connection timed out after 8 seconds — check network access, firewall rules and that the database is reachable from ParityRail. | A firewall or allowlist is dropping the packet (ETIMEDOUT). Allowlist ParityRail's egress. |
Authentication failed — check the database username and password in your connection string. | Wrong role name or password in the string (Postgres 28P01). |
Database host not found — check the hostname in your connection string. | Typo in the host (ENOTFOUND). |
Database not found — check the database name in your connection string. | Wrong database name after the last slash (Postgres 3D000). |
TLS certificate problem — try sslmode=require or supply the CA certificate. | Append ?sslmode=require to the connection string — common on self-signed or managed Postgres. |
Connection rejected — the database role is not allowed to connect from here (pg_hba.conf). | Add a pg_hba rule for the role/host (Postgres 28000). |
Test succeeds, but a later mapping step shows No tables found — check the read-only role has USAGE + SELECT grants. | The role can connect but lacks USAGE on the schema or SELECT on the tables — re-run the GRANT lines above. On the demo database, run pnpm seed first. |
| Connect fails only after you add a repair string | The repair URL is tested too, so a bad repair credential fails the whole connect. Fix it, or clear the repair field to stay detect-only. |
Invalid connection string, e.g. expected postgres://user:password@host:port/database or must start with postgres:// or postgresql:// | The pasted string isn't a valid postgres URL — check for missing pieces or stray whitespace. |
Optional: a repair role
Repairs are opt-in — leave the repair field empty above to stay detect-only. ParityRail will still flag access incidents and suggest fixes; it just won’t write anything.
mappings. The repair role limits what’s possible at the database level; your mappings limit it further.What ParityRail stores, and what it never stores
ParityRail keeps only what it needs to detect access incidents and keep the Access Ledger — a running record of each customer’s billing promises and access history. It never keeps a copy of your database.
- Stored: the connection string, encrypted, and small snapshots of just the columns you mapped — plan, premium flag, trial, entitlements. These give any access incident evidence to show you.
- Never stored: full table copies or bulk exports, plaintext credentials or passwords, or any payment method or card data.