Skip to main content
The connection string you paste into Midplane decides what an agent can reach before any policy applies. Policy is the ceiling; the database role is the floor. Give Midplane a role that already can’t do the damage you’re worried about, and the policy engine becomes your second layer rather than your only one. This page covers what every Postgres needs to have. The provider guides below cover the parts that differ — which of several connection strings to use, and where each one hides a trap.
Postgres is the only supported dialect. Any Postgres works — managed, self-run, or a read replica — as long as it meets the three requirements below.

What Midplane needs

A URL-form connection string

Midplane takes a postgres:// or postgresql:// URL:
The libpq keyword form (host=… dbname=…), a JDBC URL, and a pasted psql "…" command are all rejected with a message naming the problem. If your password contains @, :, /, ?, #, or %, percent-encode it — @ becomes %40.

A host Midplane can reach

Midplane Cloud connects to your database over the public internet, so the host must be publicly routable. Addresses that aren’t — loopback, the private ranges (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16), CGNAT, link-local, and IPv6 unique-local — are rejected before any connection is attempted. Test connection reports:
A hostname that resolves to a blocked address is rejected the same way, so an internal DNS name pointing at a private record won’t connect either. Saving such a database isn’t blocked — the connection string is only shape-checked on save — but queries against it will fail once an agent tries.Midplane Cloud doesn’t publish a fixed egress IP range, so there’s no firewall rule that admits Midplane without admitting everything else too. Don’t widen a database to the whole internet to make Cloud reach it — a database that shouldn’t have a public endpoint belongs on self-host.
Need Cloud to reach a database with no public endpoint? Self-host is the supported answer today — the same engine, policy model, dashboard, and audit trail, running where your database already is.If self-hosting isn’t workable for your team, email support@midplane.ai with a sketch of your setup — which provider, what your network policy requires, and why running Midplane yourself doesn’t fit. We’re tracking who needs this, and that’s what decides whether we build it.

A least-privilege role

Midplane enforces policy on top of your database’s permissions — it doesn’t replace them. Create a role for Midplane alone, so a policy mistake can’t become a data-loss event:
ALTER DEFAULT PRIVILEGES only applies to tables created by the role that runs it. If your migrations run as a different role, run the statement as that role too — otherwise tables created later won’t be readable.
Repeat the USAGE and SELECT grants for every schema the agent should see; public is rarely the only one. Granting writes takes two steps, in both layers. Marking a table read_write in policy lifts Midplane’s ceiling, but the query still runs as your role — so the role needs the privilege too:
A table that’s read_write in policy but has no INSERT grant will pass policy and then fail at the database. That’s the layering working as intended, but the error comes from Postgres, not from Midplane.

TLS

Add sslmode=require unless you have a reason not to. Since engine 0.15.0 Midplane follows libpq’s semantics: require encrypts without verifying the certificate, so a self-signed or private-CA database connects. To verify, pass sslrootcert=/path/to/ca.crt, or use verify-ca / verify-full. See connecting to your Postgres for the failure modes.

Point at a replica when you can

Nothing about Midplane requires the primary. If your agent’s job is analysis, give it a read replica’s connection string: the replica physically cannot accept a write, so a policy gap and a database gap have to line up before anything is modified. You still get the audit trail and column masking on every query. Reach for the primary only when the agent genuinely needs to write — and then grant it per table, with write approvals on anything you’d want a human to see first.

Provider guides

Supabase

Which of the four connection strings to use, and the pooler username trap.

Neon

Pooled vs direct endpoints, SNI routing, and pointing an agent at a branch.

Amazon RDS & Aurora

Reachability from Cloud, rds.force_ssl, and why IAM auth doesn’t fit.

Railway

Why the internal hostname fails, and the TCP proxy that fixes it.
Using something else? Every other Postgres — Google Cloud SQL, Azure Database, Heroku, Fly, Render, Timescale, Crunchy, or your own — follows the three requirements above with no extra steps. Start with the quickstart.