Lymeno
← All articles

Guides2 min read

Give every agent its own expiring database role

A dedicated role per agent, limited to the permissions its task needs and set to expire, makes access easy to reason about and easy to end.

The fastest way to connect an agent to a database is to give it the owner password. It is also the hardest to undo: every agent shares one credential, you cannot revoke one without breaking the others, and the database cannot tell you which agent ran which statement.

A better default is one database role per agent, created for its task and set to expire when the task should be over. This guide shows how to do that with the Lymeno API.

Create a role for the task

curl -X POST https://console.lymeno.com/v1/databases/$DATABASE_ID/roles \
  -H "Authorization: Bearer $LYMENO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{
    "username": "agent_report_0412",
    "inheritedRoles": ["pg_read_all_data"],
    "validUntil": "2026-10-04T00:00:00Z"
  }'

The request takes three fields:

  • username: 3–63 characters, starting with a lowercase letter and containing only lowercase letters, digits, and underscores. Names reserved by PostgreSQL or Lymeno, such as postgres, admin, and names that start with pg_, are rejected.
  • inheritedRoles: the permissions the role receives. At least one is required.
  • validUntil: an optional expiration time in ISO 8601 format, which must be in the future. If you omit it, the role does not expire.

The response contains the role, the ID of the operation that creates it, and the password. The password is returned only in this response. Store it where the agent can read it, such as the agent’s secret store, before you do anything else.

Grant only what the task needs

inheritedRoles accepts a fixed set of values:

Role What it allows
owner Owns the public schema; can create and change tables
pg_read_all_data Read all tables, views, and sequences
pg_write_all_data Insert, update, and delete in all tables
pg_read_all_stats Read all statistics views
pg_monitor Read monitoring views and functions
pg_signal_backend Cancel queries and end sessions of other roles
pg_maintain Run VACUUM, ANALYZE, REINDEX, and similar maintenance commands

Every role except owner is a PostgreSQL built-in role with its standard meaning. A reporting agent needs pg_read_all_data and nothing else. A migration agent needs owner. Agents that only watch for slow queries need pg_monitor.

On-demand databases currently support owner, pg_monitor, and pg_signal_backend. Other values return validation_failed with the reason role_not_supported.

Let access end on its own

validUntil maps to PostgreSQL’s VALID UNTIL. After that time, PostgreSQL rejects new logins for the role, so access ends even if nobody remembers to clean up.

Two details are worth knowing:

  • Expiration applies to new connections. Sessions that are already open keep running until they disconnect. If an agent holds a long-lived connection pool, close it when the task ends.
  • An expired role still exists. Delete it with DELETE /v1/databases/:id/roles/:roleId when you no longer need it. Each database can have up to 20 roles.

Pair roles with scoped API tokens

The database role controls what an agent can do inside PostgreSQL. The API token controls what it can do in Lymeno. Apply the same principles to both:

  • Create a token for each agent or automation, not one token for everything.
  • Give tokens that only read state the read-only member role, and give admin only to tokens that need to make changes.
  • Set tokens to expire after 30, 90, or 365 days.
  • API tokens cannot create or revoke other tokens, so a leaked token cannot issue new ones.

Every change made with a token is recorded in the audit log under that token’s name. When each agent has its own token and its own role, the audit log and the database’s own logs tell the same story: which agent did what, and when.

Create the first database for your agents

Sign up and create an API token to begin.