User Guide

Executor privileges

pgroles does not require superuser. It needs CREATEROLE plus a handful of scoped grants, and the exact set depends on whether the roles you manage are new or already exist.


What pgroles actually needs

This table was verified against a live PostgreSQL 16 server. CREATEROLE is the load-bearing attribute; everything else is either automatic (for roles the executor created itself) or a narrow, explicit grant.

pgroles operationRequires
CREATE ROLECREATEROLE attribute
ALTER ROLE / COMMENT ON ROLE / passwords / ALTER ROLE ... SET configCREATEROLE + ADMIN OPTION on the target role (automatic for roles the executor created itself)
GRANT/REVOKE role membershipsADMIN OPTION on the granted (group) role — automatic for roles the executor created
DROP ROLECREATEROLE + ADMIN OPTION on the role
CREATE SCHEMACREATE privilege on the database
ALTER SCHEMA ... OWNER TOownership of the schema plus membership in the new owner role
GRANT/REVOKE on tables/sequences/functionsownership of the objects, directly or via membership in the owning role
ALTER DEFAULT PRIVILEGES FOR ROLE xmembership (privileges) of role xADMIN OPTION alone is not enough
REASSIGN OWNED BY a TO b (retirements)membership (privileges) of both a and b. The executor has ADMIN OPTION on roles it created, so it can GRANT a TO executor itself first — pgroles does not do this automatically
DROP OWNED BY a (retirements)membership (privileges) of a
terminate_sessions (retirements)membership in pg_signal_backend (cannot terminate superuser sessions)
inspection (diff/plan/generate)none beyond CONNECTpg_roles, pg_shdescription, and ACL columns are readable by any role

Why greenfield is nearly free and brownfield has friction

PostgreSQL 16 changed CREATEROLE semantics: a role with CREATEROLE automatically receives ADMIN OPTION on any role it creates. That collapses most of the table above into a single attribute for a greenfield executor — one that creates every role it will later alter, grant, or drop. A fresh executor needs only:

  • CREATEROLE
  • CREATE on the target database (to create schemas)
  • membership in the schema-owner role(s) it manages default privileges for

The friction shows up in brownfield adoption. CREATEROLE does not retroactively grant ADMIN OPTION on roles that already existed before the executor was created. For every pre-existing role pgroles needs to alter, drop, or manage memberships on, a superuser or existing admin must explicitly grant the executor admin rights:

GRANT adopted_role TO executor WITH ADMIN TRUE;

Without this, pgroles can still create new roles and manage grants on objects the executor owns, but altering or dropping the adopted role, or changing its memberships, fails with a permission error. See the staged adoption guide for the broader brownfield rollout sequence.

Bootstrap SQL

Run once, by a superuser or an existing admin (RDS rds_superuser member, Cloud SQL cloudsqlsuperuser member, AlloyDB alloydbsuperuser member, etc.), before pointing pgroles at a database for the first time:

-- Run once as superuser / cloud admin user.

-- 1. The role pgroles connects as.
CREATE ROLE pgroles_executor WITH LOGIN PASSWORD '...' CREATEROLE;

-- 2. Let it create schemas in the target database.
GRANT CREATE ON DATABASE mydb TO pgroles_executor;

-- 3. If pgroles will manage default privileges owned by an existing
--    schema-owner role, give the executor membership in that role.
GRANT app_owner TO pgroles_executor;

-- 4. Brownfield only: for each pre-existing role pgroles must alter,
--    drop, or manage memberships on, grant explicit admin rights.
GRANT some_preexisting_role TO pgroles_executor WITH ADMIN TRUE;

Steps 1–2 cover a greenfield executor. Steps 3–4 are additive, per-role grants you add as you bring existing roles under pgroles management.

Cloud providers

None of RDS, Cloud SQL, AlloyDB, or Azure Database for PostgreSQL expose true superuser. The bootstrap above is run by the provider's admin user instead — rds_superuser member on RDS/Aurora, cloudsqlsuperuser member on Cloud SQL, alloydbsuperuser member on AlloyDB. See the AWS RDS & Aurora and Google Cloud SQL pages for the specific attributes those admin roles lack and how pgroles adapts around them.

For Cloud SQL IAM authentication, the operator can authenticate as a low-privilege IAM identity and SET ROLE to a privileged parent role on every connection via connection.params.setRole — see the operator connection docs for the full pattern.

The superuser shortcut

Running pgroles as superuser works and satisfies every row in the table above automatically — there is nothing to grant, adopt, or troubleshoot. The cost is the one every DBA already weighs: the connection can do anything to the cluster, not just what pgroles' manifest describes. Scoped CREATEROLE privileges are the recommended default; superuser is a pragmatic fallback for small or throwaway environments.