Connect Postgres

Set up a PostgreSQL connection — required fields, TLS mode, and least-privilege credentials for a read-only analytics role.

This page covers connecting a PostgreSQL database (or a Postgres-compatible warehouse) to Flax. Add the connection from the Data page at /app/data.

#Required fields

Field Description
host Hostname of the Postgres server.
port Server port (typically 5432).
database The database to query.
user Login role used for queries.
password Stored as the connection secret, encrypted at rest.

TLS is negotiated with sslmode, which defaults to prefer when unset. Use a stricter mode such as require for connections that cross a public network.

#Least-privilege credentials

Create a dedicated role for Flax rather than reusing an application or admin login. Grant it only what analytics needs:

CREATE ROLE flax_reader LOGIN PASSWORD '…';
GRANT CONNECT ON DATABASE analytics TO flax_reader;
GRANT USAGE ON SCHEMA public TO flax_reader;
GRANT SELECT ON ALL TABLES IN SCHEMA public TO flax_reader;

Flax only issues read queries, so a SELECT-only role is sufficient. Scope the grants to the schemas your semantic model actually references.

Tip

After saving, use the connection test on the Data page to confirm Flax can reach the host and authenticate before you build models on it.

#Connecting a database behind a firewall

If your database only accepts connections from known IPs, allow Flax's outbound (egress) address so its queries can reach you. Flax connects from a single static IP:

Flax hosting Egress IP to allowlist
Flax Cloud (flax-analytics.com) 195.201.255.126
Self-hosted Your server's own outbound IP

Add that address to your database firewall / cloud security group / pg_hba.conf, alongside the least-privilege role above.

Prefer not to expose a public endpoint at all? Under Private network access in the connection form, pick one of two outbound-only tunnels — the database never needs a public address:

  • SSH bastion tunnel — Flax dials your bastion (egress-checked), then reaches the database from the far side. Provide the bastion host/user and pin its host key.
  • Cloudflare Access tunnel — reach a database on a private network through your own Cloudflare Tunnel, with zero inbound firewall exposure (see below).

#Cloudflare Access tunnel

If you already run Cloudflare Tunnel, Flax can connect over it — no open port, no bastion, nothing to install on Flax's side. One-time setup:

  1. Publish the database as a TCP service on the tunnel. In your cloudflared config:

    ingress:
      - hostname: bi-db.example.com
        service: tcp://10.0.0.5:5432
      - service: http_status:404

    Then cloudflared tunnel route dns <tunnel> bi-db.example.com and reload cloudflared.

  2. Add a Zero Trust Access application for that hostname with a policy whose action is Service Auth (not Allow — Allow expects a browser identity). Optionally also require Flax's egress IP (195.201.255.126) as a source, restoring an IP allowlist.

  3. Create a service token and enter its Client ID and Client Secret, plus the hostname, in the connection form's Cloudflare Access tunnel fields. Both token halves are stored encrypted at rest.

Flax reaches the database by opening an Access-authenticated WebSocket to that hostname and tunneling the Postgres protocol over it — the public hop is SSRF-checked, and your database stays private (ADR-0061).

Note

Self-hosting? The egress IP is your own server's outbound address. Pin it to a reserved/floating IP so it survives host rebuilds — see deploy/provision/egress-ip.sh in the repo.

#Query execution

Queries you build in Explore are compiled to Postgres SQL and pushed down to your database (ADR-0004) — Flax never pulls whole tables to filter them locally. Repeated queries can be served from the result cache; see Caching & performance.