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 apostgres:// or postgresql:// URL:
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
- Cloud
- Local
- Self-host
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 (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.
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: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: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:
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
Addsslmode=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.