Manage database service accounts
Database service accounts can be as simple as a user with a separate password or certificate for authentication. More advanced users may wish to set up accounts where permission scope can be changed dynamically with SET ROLE to enable quick switching between profiles without logging out or reloading content.
Overview
SET ROLE can be used to dynamically scope permissions for a service account during a session. This works by limiting a user's effective permissions to only those granted by the activated role(s). This approach has several advantages:
- Service accounts can be assigned multiple roles, but only activate the one needed for a specific query.
- Attackers can only use the active role's permissions if the service account is compromised.
- A single account can perform diverse tasks by switching roles rather than requiring separate credentials for each task.
- Permissions can be updated for an entire class of service accounts by modifying one role instead of updating individual users.
- Logs can track which specific role was active during a query, providing clearer context for security audits.
In practice, you:
- Design roles that encode the alowed boundaries (read_only, maintenance, etc.)
- Grant them to the service account
- At connection time, choose the active role(s) via
SET ROLE(or role parameter), thereby constraining what that session can do
Set up a service role
Grant roles to the service account
First, create roles with the privileges/ settings you want, then grant them to the service account.
Use SET ROLE to define session boundaries
At the start of a session, the service account chooses which roles are active:
or:
SET ROLE activates roles for the current user; the effective privileges are the union of all active roles plus ay directly granted to the user.
You can also deactivate all roles:
or activate multiple roles:
The currently active roles can be inspected via system.current_roles.
Set default roles for the service account
To ensure the service account always starts in a restricted mode, configure default roles:
or
Using SET ROLE over HTTP / programmatically
If the service account connects via HTTP, you cannot send SET ROLE; SELECT ... as a multi-statement. Instead, pass the role as a query parameter:
?role=... is equivalent to executing SET ROLE read_only_role before the statement. Multiple role parameters behave like SET ROLE role 1, role 2.
Some drivers (e.g. ClickHouse Connect for Python) also expose a role setting that is sent with each request, which the server uses as the session role.