reader / writer / admin for every end user. Each credential also has a unique username that Airhouse stores with the subject you supplied, so queries can be traced back to one of your users.
When to use service accounts
Use a service account when:- Your users sign in to your application, not directly to Airhouse.
- Each user’s queries should run with that user’s own role.
- You don’t want to manage a long-lived Airhouse password per user.
Create a service account
Service accounts are created with the Admin API using the operator’s admin token. Each service account is bound to exactly one database and has two caps: the highest role it may mint (max_role) and the longest lifetime it may mint (max_ttl_secs, at most 86,400 seconds).
bearer key:
Mint a credential
When a user signs in to your application, mint a credential for them with the service-account bearer:
The response is a ready-to-use Postgres credential:
dbname set to tenant, and user and password from the response:
expires_at, the credential stops authenticating with SQLSTATE 28P01, the same error as a wrong password. Mint once per session, not once per query: a credential can run any number of queries until it expires.
Example: Python backend
Example: Node.js backend
Schema-scoped writers
If several applications share one database, you can mint awriter that may write only inside specific schemas, typically the application’s own schema. It can still read everything, like any writer:
"write_schemas": ["app_store_ops"]. Treat a response without a matching echo as a failure: don’t hand out the credential, and revoke it.
Rules for write_schemas:
- Only allowed with
"role": "writer". - One to 64 entries, each a lowercase identifier (letters, digits, and underscores, starting with a letter or underscore, at most 63 characters), with no duplicates.
memory,system,temp, and names starting with__ducklake_metadata_aren’t allowed.
- Read any table in the database.
- Write with
INSERT,UPDATE,DELETE,MERGE,TRUNCATE, andCOPY ... FROM STDIN, but only to tables named asschema.table(orlake.schema.table) in an allowed schema. Unqualified table names are refused. - Run DDL inside its schemas:
CREATE SCHEMAfor an allowed schema, andCREATE,ALTER, andDROPfor tables and views in allowed schemas. Unlike an unscoped writer, a scoped writer can create its own tables. - Use
BEGIN,COMMIT, andROLLBACK, and theSETstatements drivers send while connecting.
ATTACH, USE, SET search_path, INSTALL, LOAD, DROP SCHEMA, CREATE TEMP ..., table functions other than range, generate_series, and unnest, multiple statements in one query, and SQL syntax the scope checker can’t parse (for example time travel with AT (VERSION => n)). A refusal is SQLSTATE 42501:
GET /admin/v1/capabilities with your bearer. It returns {"mint.write_schemas": true} on servers that support the feature.
Revoke credentials
Revoke one minted credential early, for example when a user signs out:Rate limits
Each service account can mint 60 credentials per minute by default. Past the limit, the mint endpoint returns429 Too Many Requests. Operators can change the limit with mint_rate_limit_per_min (see the configuration reference).
Errors
For the full list of endpoints, see the Admin API reference.