Connecting to PostgreSQL
PostgreSQL is a powerful open-source relational database. flAPI can query PostgreSQL databases directly or cache results for high-performance API serving.
Setup
# flapi.yaml
connections:
postgres-db:
init: |
INSTALL postgres;
LOAD postgres;
properties:
host: localhost
port: '5432'
database: mydb
user: '${POSTGRES_USER}'
password: '${POSTGRES_PASSWORD}'
Connection properties are accessible inside SQL templates as {{ conn.host }}, {{ conn.database }}, etc.
Environment Variables
Store sensitive credentials in environment variables:
export POSTGRES_USER=myuser
export POSTGRES_PASSWORD=mypassword
# flapi.yaml
template:
environment-whitelist:
- '^POSTGRES_.*'
Querying PostgreSQL
The DuckDB Postgres extension typically reads its target via ATTACH (recommended) or postgres_scan once the connection is attached. Use init to attach the database, then reference it in templates.
Attach Pattern (recommended)
connections:
postgres-db:
init: |
INSTALL postgres;
LOAD postgres;
ATTACH IF NOT EXISTS 'host={{ conn.host }} port={{ conn.port }} dbname={{ conn.database }} user={{ conn.user }} password={{ conn.password }}' AS pg (TYPE postgres);
properties:
host: localhost
port: '5432'
database: mydb
user: '${POSTGRES_USER}'
password: '${POSTGRES_PASSWORD}'
-- Query an attached PostgreSQL table
SELECT *
FROM pg.public.users
WHERE active = true
{{#params.role}}
AND role = '{{{ params.role }}}'
{{/params.role}}
Example: User API
Endpoint (sqls/users.yaml):
url-path: /users/
method: GET
request:
- field-name: role
field-in: query
required: false
validators:
- type: enum
allowedValues: ['admin', 'user', 'guest']
- field-name: active
field-in: query
required: false
validators:
- type: enum
allowedValues: ['true', 'false']
template-source: users.sql
connection:
- postgres-db
Template (sqls/users.sql):
SELECT
id,
username,
email,
role,
created_at
FROM pg.public.users
WHERE 1=1
{{#params.active}}
AND active = {{ params.active }}
{{/params.active}}
{{#params.role}}
AND role = '{{{ params.role }}}'
{{/params.role}}
ORDER BY created_at DESC
LIMIT 100
Boolean and floating-point request parameters arrive as strings. Use an enum validator with the allowed string values (["true", "false"]) or a string validator with a regex: constraint. flAPI ships seven validator types: int, string, enum, email, uuid, date, time.
With Caching
For high-traffic APIs, cache PostgreSQL data through DuckLake:
Cache Template (sqls/users_cache.sql):
INSERT INTO {{cache.catalog}}.{{cache.schema}}.{{cache.table}}
SELECT
user_id,
username,
email,
role,
last_login
FROM pg.public.users
WHERE active = true
Endpoint configuration:
cache:
enabled: true
table: users_cache
schema: analytics
schedule: 15m # Refresh every 15 minutes
template-file: users_cache.sql
Connection Pooling
The DuckDB Postgres extension manages its own pool when you ATTACH the database. Tune behavior with the upstream extension settings (pg_pages_per_task, pg_use_binary_copy, etc.) inside init: if needed — see the DuckDB Postgres extension docs.
Next Steps
- BigQuery Connection: Connect to BigQuery
- Parquet Files: Work with file formats
- Caching Setup: Cache PostgreSQL data