PostgreSQL.
Connect Orchid to any PostgreSQL-compatible database — self-hosted PostgreSQL, managed RDS, Cloud SQL, Neon, Crunchy Bridge, Aurora-PostgreSQL, Timescale.
Requirements
- PostgreSQL 12 or newer (older versions work but aren't tested).
- A database user with at least
USAGEon the schema andSELECTon the tables you want to query. - Network reachability from your machine — direct, VPN, or SSH tunnel.
Connect
- Open Integrations → + Add connection → PostgreSQL.
- Fill in the fields:
- Host — e.g.
db.example.comor10.0.0.5 - Port —
5432by default - Database — the postgres database name (not the cluster)
- User / Password — credentials
- Host — e.g.
- Click Test connection. Green check = ready.
Test from the command line first
If the form fails, try the same credentials from your shell — it isolates Orchid from the wire problem.
$ psql "postgresql://orchid_user:secret@db.example.com:5432/analytics?sslmode=require"
psql (16.2)
SSL connection (protocol: TLSv1.3, cipher: TLS_AES_256_GCM_SHA384)
Type "help" for help.
analytics=> SELECT version();
If psql connects and Orchid does not, the issue is almost always SSL mode or an outbound proxy. Match the sslmode from your psql string to the SSL toggle.
Optional settings
SSL
Toggle Require SSL if your server enforces it. RDS, Cloud SQL, Supabase, Neon, and most managed providers do. Upload a CA cert if your server requires verification beyond the default trust store.
SSH tunnel
For databases behind a bastion host, toggle Use SSH tunnel and provide:
- Tunnel host + port (typically
22) - Tunnel username
- Private key (paste or upload)
End-to-end, an SSH tunnel walkthrough looks like this. From a fresh machine:
$ ssh-keygen -t ed25519 -f ~/.ssh/orchid_bastion -C "orchid-bastion"
$ ssh-copy-id -i ~/.ssh/orchid_bastion.pub ec2-user@bastion.example.com
$ ssh -i ~/.ssh/orchid_bastion ec2-user@bastion.example.com "echo ok"
ok
Then in Orchid: toggle Use SSH tunnel, set host to bastion.example.com, port 22, user ec2-user, paste the contents of ~/.ssh/orchid_bastion into the private-key field. Keep the database host/port as the private endpoint (e.g. 10.0.0.5:5432) — Orchid resolves it through the tunnel.
Default schema
You can pin a default schema in the connection settings. Useful if your database has many schemas and you want unqualified queries to hit one of them.
Common gotchas
- "password authentication failed for user" — check that
pg_hba.confallows your IP and that the password is correct. Some managed providers use a different password for direct connections than for their web UI. - "no pg_hba.conf entry for host" — your IP isn't whitelisted. Add it in the provider's firewall, or use the SSH tunnel.
- Schema appears empty — the user has
CONNECTbut notUSAGEon the schema. RunGRANT USAGE ON SCHEMA public TO orchid_user;on the database. - TLS handshake fails — server requires SSL but the toggle is off, or vice versa.
- "canceling statement due to statement timeout" — your role has a
statement_timeout. Override per-cell withSET LOCAL statement_timeout = '5min';at the top of the cell. - Logical replication slot exhaustion — PostgreSQL caps the number of replication slots (default 10). If you connect to a primary with logical replication enabled and see
all replication slots are in use, you're hitting a server-side limit, not an Orchid bug. Drop unused slots:SELECT pg_drop_replication_slot('name'); - Long-running cells and transaction isolation — Orchid runs each cell in its own implicit transaction at
READ COMMITTED. If you needREPEATABLE READ(e.g. for a multi-statement analytical snapshot), wrap the cell inBEGIN ISOLATION LEVEL REPEATABLE READ; ... COMMIT;. Long open transactions can blockVACUUM, so close them quickly.
New PostgreSQL connections are read-only. Flip the Allow writes toggle in the connection settings to enable INSERT / UPDATE / DELETE. A lock icon appears on every cell that uses a write-enabled connection.
Example queries
-- See all user tables
SELECT schemaname, tablename
FROM pg_tables
WHERE schemaname NOT IN ('pg_catalog', 'information_schema')
ORDER BY schemaname, tablename;
-- Daily activity for the last 30 days
SELECT date_trunc('day', created_at) AS day,
count(*) AS events
FROM events
WHERE created_at > now() - interval '30 days'
GROUP BY 1
ORDER BY 1;
-- Slowest 10 queries this session
SELECT query, total_exec_time, calls, mean_exec_time
FROM pg_stat_statements
ORDER BY total_exec_time DESC
LIMIT 10;
Where to go next
For more on writing SQL cells, see SQL cells.