---
title: "Connect PostgreSQL"
description: "Connect Datarelix to PostgreSQL: create a read-only user, pick username/password or connection-string auth, scope schemas, and handle poolers like PgBouncer."
canonical: https://docs.datarelix.ai/guides/connections/postgres/
---

# Connect PostgreSQL

Datarelix connects to PostgreSQL through a read-only query service. All queries are validated and executed inside that service — the model never sees credentials or executes raw SQL against your database.

## Prerequisites

- A PostgreSQL server (any actively supported version — 13+).
- A database role with `CONNECT` on the database and `USAGE` + `SELECT` on the schemas/tables you want to analyze. Make it a `LOGIN` role that is **not** a superuser and has no write privileges.
- Network reachability from Datarelix's egress IPs to your Postgres server.

## Auth modes

### Username & password

Standard SQL authentication using a database username and password. The password is stored encrypted; all other connection fields are stored as plain configuration.

**Setup — create a read-only role**

Run the following in your database (as a superuser or role with `CREATEROLE`):

```sql
CREATE USER datarelix_reader WITH PASSWORD 'choose-a-strong-password';
GRANT CONNECT ON DATABASE your_db TO datarelix_reader;
GRANT USAGE ON SCHEMA public TO datarelix_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO datarelix_reader;
ALTER DEFAULT PRIVILEGES IN SCHEMA public
  GRANT SELECT ON TABLES TO datarelix_reader;
```

Replace `your_db` and `public` with your actual database and schema names. See the PostgreSQL [`GRANT` reference](https://www.postgresql.org/docs/current/sql-grant.html) for the full privilege model.

**Where to find your credentials**

| Field | Where to get it |
|-------|----------------|
| Host | Your cloud console — [AWS RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ConnectToPostgreSQLInstance.html): instance endpoint; [GCP Cloud SQL](https://cloud.google.com/sql/docs/postgres/connect-overview): public or private IP; [Azure Database for PostgreSQL](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/quickstart-create-server): server hostname (`*.postgres.database.azure.com`) |
| Port | Default `5432`; visible under the connection info panel in your cloud console |
| Database | The database name — list with `\l` in psql |
| Username | The role you created above |
| Password | The password you set in `CREATE USER` |

**What to enter**

```ini
Host:            your-host.example.com
Port:            5432
Database:        your_db
Username:        datarelix_reader
Password:        ••••••••
SSL mode:        require
Allowed schema:  public
```

---

### Connection string

Paste a `postgresql://` URL instead of filling individual fields. Useful when your cloud provider gives you a ready-made connection string.

**Where to find your connection string**

- **[AWS RDS](https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/USER_ConnectToPostgreSQLInstance.html)** — RDS console → your DB instance → **Connectivity & security** → copy the endpoint hostname, then build: `postgresql://datarelix_reader:password@endpoint:5432/dbname?sslmode=require`
- **[GCP Cloud SQL](https://cloud.google.com/sql/docs/postgres/connect-overview)** — Cloud SQL → your instance → **Overview** → copy the public IP; or use the Cloud SQL Auth Proxy hostname for private connectivity
- **[Azure Database for PostgreSQL](https://learn.microsoft.com/en-us/azure/postgresql/flexible-server/quickstart-create-server)** — Azure portal → your server → **Connect** → copy the connection details and swap in your password
- **[Supabase](https://supabase.com/docs/guides/database/connecting-to-postgres)** — Project settings → **Database** → **Connection string** → URI tab
- **[Neon](https://neon.com/docs/connect/connect-from-any-app)** — Dashboard → your project → **Connection Details** → copy the connection string

**What to enter**

```
postgresql://datarelix_reader:your-password@your-host.example.com:5432/your_db?sslmode=require
```

### Connection poolers (transaction vs session mode)

Some managed providers front Postgres with a connection pooler, and the mode matters:

- **Session-mode poolers** and **direct connections** behave like normal Postgres — use these.
- **Transaction-mode poolers do not support prepared statements**, which the read-only query service relies on. Connecting through one fails with prepared-statement errors.

Provider specifics:

- **Supabase** — use the **Direct connection** or **Session pooler** (port `5432`). Avoid the **Transaction pooler** (port `6543`). Note the pooler username is `postgres.<project-ref>`, not `postgres`. See [Supabase connection methods](https://supabase.com/docs/guides/database/connecting-to-postgres).
- **Self-managed PgBouncer** — point Datarelix at a `session`-mode port, not a `transaction`-mode one.

---

## SSL modes

The **SSL mode** field maps to libpq's [standard SSL modes](https://www.postgresql.org/docs/current/libpq-ssl.html):

| Mode | Meaning |
|------|---------|
| `disable` | No TLS. Don't use over public networks. |
| `allow` / `prefer` | Try TLS, fall back to plaintext if the server doesn't support it. |
| `require` | TLS required; server cert **not** verified. Default. Protects against passive eavesdropping but not active MITM. |
| `verify-ca` | TLS + verify the server cert chains to a trusted CA. |
| `verify-full` | TLS + verify the cert **and** the hostname matches. Strongest. Recommended for managed Postgres in production. |

## Scope semantics

The **Allowed schema** field limits introspection and queries to one schema. Default: `public`.

To analyze multiple schemas in the same database, create one connection per schema.

## Discovery

Fully supported. The introspector queries `information_schema.tables`, `information_schema.columns`, and `pg_catalog.pg_constraint` to surface primary keys, foreign keys, nullability, defaults, and types. The optional LLM enrichment pass adds descriptions and infers undeclared relationships from naming conventions.

## Limitations

- No write or DDL queries — the validator rejects mutations at the AST layer.
- One schema per connection.
- Server-side row cap is enforced — queries without a `LIMIT` get one appended automatically.

## Troubleshooting

| Symptom | Likely cause | Fix |
|---------|--------------|-----|
| `Connection refused` | Firewall or wrong port | Verify `psql -h host -p 5432 -U user db` works from the same network. |
| `password authentication failed` | Bad credentials or wrong `pg_hba.conf` method | Test with `psql` first; check the role's expected auth method. On Azure, use the plain username — Flexible Server does **not** need the `user@servername` suffix (that was only for the retired Single Server). On Supabase poolers the username is `postgres.<project-ref>`. |
| `prepared statement ... already exists` / `does not exist` | Connecting through a transaction-mode pooler | Use a session-mode pooler or direct connection (Supabase: port `5432`, not `6543`). |
| `SSL connection required` | Server enforces TLS, mode is `disable`/`prefer` | Set SSL mode to `require` or stronger. |
| `relation does not exist` | Wrong schema | Set **Allowed schema** to the schema that owns the table; `\dn` in psql lists schemas. |
| `permission denied for table X` | Role lacks `SELECT` on the table | `GRANT SELECT ON ALL TABLES IN SCHEMA X TO role` plus `ALTER DEFAULT PRIVILEGES IN SCHEMA X GRANT SELECT ON TABLES TO role` for future tables. |
