5.2 Roles, Privileges & Object Ownership
Key Takeaways
- In PostgreSQL, users and groups are completely unified into a single database object concept: the ROLE; CREATE USER is simply an alias for CREATE ROLE ... LOGIN.
- Role attributes such as SUPERUSER, CREATEDB, CREATEROLE, REPLICATION, and LOGIN govern cluster-wide capabilities and bypass object-level access control checks.
- Role inheritance defaults to INHERIT, allowing member roles to automatically assume object permissions granted to their parent group roles without running SET ROLE.
- Only the object owner or a superuser can alter, drop, or reassign privileges on a database object; object ownership transfer is performed via ALTER TABLE ... OWNER TO.
- ALTER DEFAULT PRIVILEGES defines automatic permission grants for future objects created by specified roles, eliminating permission gaps in shared production schemas.
5.2 Roles, Privileges & Object Ownership
[!NOTE] Historical Evolution: In early versions of PostgreSQL (prior to 8.1), user accounts and group accounts were distinct catalog entities managed via
CREATE USERandCREATE GROUP. Since PostgreSQL 8.1, these concepts have been completely unified under the single concept of aROLE. A user is simply a role with theLOGINattribute, while a group is a role withoutLOGINthat contains member roles.
PostgreSQL employs a comprehensive, granular Discretionary Access Control (DAC) model, optionally extended by Row-Level Security (RLS) policies on individual tables. Understanding role attributes, object ownership, and privilege propagation is central to securing production PostgreSQL databases and excelling on the certification exam.
The Unified Role Model
A role is an entity that can own database objects and hold database privileges. Roles are cluster-global: they exist across all databases in the cluster and are defined in the shared system catalogs (pg_authid and the pg_roles system view).
-- CREATE USER is syntactic sugar for CREATE ROLE ... LOGIN
CREATE ROLE app_user WITH LOGIN PASSWORD 'SecureSecret123!';
-- Exactly equivalent to:
CREATE USER app_user WITH PASSWORD 'SecureSecret123!';
-- Creating a group role (no LOGIN attribute by default)
CREATE ROLE sales_team;
System Catalogs for Roles
pg_authid: The actual physical catalog table storing all role definitions and authentication secrets (e.g.,scram-sha-256password hashes). It is strictly protected and readable only by superusers.pg_roles: A publicly accessible system view that displays role metadata while masking the sensitive password hash column (rolpasswordshows as********).
Key Role Attributes
When defining or altering a role, administrators assign specific administrative attributes that govern system-level privileges:
CREATE ROLE dev_admin WITH
LOGIN
CREATEDB
CREATEROLE
INHERIT
CONNECTION LIMIT 20
PASSWORD 'StrongPassword#2026';
| Attribute | Description & Security Impact |
|---|---|
LOGIN / NOLOGIN | Determines whether the role can be used as an initial connection credential. Without LOGIN, the role functions purely as a group. |
SUPERUSER / NOSUPERUSER | Bypasses all internal permission checks, object ownership requirements, and Row-Level Security policies. Only superusers can create other superusers. |
CREATEDB / NOCREATEDB | Grants the ability to create new databases within the cluster. The creating role automatically becomes the owner of the new database. |
CREATEROLE / NOCREATEROLE | Grants the ability to create, alter, and drop other non-superuser roles, as well as manage group memberships. |
REPLICATION / NOREPLICATION | Permits the role to initiate physical streaming replication connections and create replication slots (required for high availability and logical replication). |
INHERIT / NOINHERIT | Governs privilege inheritance. Enabled by default (INHERIT). Determines if member roles automatically inherit permissions from granted group roles. |
BYPASSRLS / NOBYPASSRLS | Allows a non-superuser role to bypass all active Row-Level Security policies. |
CONNECTION LIMIT | Enforces a hard cap on concurrent active connections established by this specific role (-1 indicates unlimited). |
[!CAUTION] SUPERUSER Omnipotence: A role with
SUPERUSERbypasses all access privilege checks inside the database. It can read, modify, or truncate any table, alter any function, and read sensitive files from the server filesystem via functions likepg_read_file(). Enterprise security standards dictate minimizing the use of superuser accounts in application connection strings.
Role Membership and Privilege Inheritance
PostgreSQL implements role hierarchies by granting one role to another:
-- Create group roles
CREATE ROLE readonly_analysts;
CREATE ROLE engineering_group;
-- Create individual login user
CREATE ROLE alice WITH LOGIN PASSWORD 'AlicePassword!2026';
-- Grant group membership to alice
GRANT readonly_analysts TO alice;
GRANT engineering_group TO alice WITH ADMIN OPTION;
INHERIT vs. NOINHERIT
Privilege inheritance determines how a user exercises the permissions of their group roles:
-
INHERIT(Default):- Alice automatically possesses every permission granted to
readonly_analysts(e.g.,SELECTon sales tables) without executing any preparatory commands. - System-level role attributes (like
CREATEDB,CREATEROLE,SUPERUSER) are never inherited; only object permissions (SELECT,INSERT,UPDATE,DELETE,USAGE) are inherited.
- Alice automatically possesses every permission granted to
-
NOINHERIT:- Alice does not automatically possess group permissions.
- To use the permissions granted to
readonly_analysts, Alice must explicitly execute theSET ROLEcommand during her active session:SET ROLE readonly_analysts; -- Current session now acts with readonly_analysts privileges RESET ROLE; -- Reverts session identity back to alice
The WITH ADMIN OPTION Clause
When granting role membership WITH ADMIN OPTION, the member role (Alice) is authorized to grant or revoke membership in that group to other database roles, without possessing the cluster-wide CREATEROLE attribute.
Object Privileges & Access Control (DCL)
Database objects (tables, views, schemas, sequences, functions) are protected by an Access Control List (ACL). Privileges are assigned using GRANT and removed using REVOKE.
+-------------------------------------------------------------------------+
| Relational Object Access Pipeline |
+-------------------------------------------------------------------------+
| Client queries: SELECT * FROM sales.orders; |
| |
| Step 1: Does the role have USAGE privilege on schema 'sales'? |
| ├── NO -> ERROR: permission denied for schema sales |
| └── YES -> Proceed to Step 2 |
| |
| Step 2: Does the role have SELECT privilege on table 'orders'? |
| ├── NO -> ERROR: permission denied for table orders |
| └── YES -> Execute Query |
+-------------------------------------------------------------------------+
Crucial Schema Requirement: The USAGE Privilege
A common administration pitfall occurs when an administrator grants SELECT on a table, but the user still receives permission denied:
-- Fails if user lacks USAGE on the schema!
GRANT SELECT ON sales.orders TO alice;
-- Mandatory prerequisite:
GRANT USAGE ON SCHEMA sales TO alice;
Without USAGE on the parent schema, a role cannot look up or access any object contained inside that schema, regardless of table-level grants.
Granting and Revoking Table Privileges
-- Grant specific DML privileges on a table
GRANT SELECT, INSERT, UPDATE ON TABLE sales.orders TO alice;
-- Grant all privileges on all existing tables in a schema
GRANT ALL PRIVILEGES ON ALL TABLES IN SCHEMA sales TO engineering_group;
-- Revoke privileges
REVOKE INSERT, UPDATE ON TABLE sales.orders FROM alice;
-- The PUBLIC pseudo-role (represents all current and future roles)
REVOKE ALL ON SCHEMA public FROM PUBLIC;
The WITH GRANT OPTION Clause
If a privilege is granted WITH GRANT OPTION, the recipient can grant that same privilege to other roles:
GRANT SELECT ON TABLE sales.orders TO alice WITH GRANT OPTION;
When revoking privileges granted with grant options, the administrator must choose between RESTRICT and CASCADE:
REVOKE SELECT ON TABLE sales.orders FROM alice RESTRICT;: Fails if Alice has granted the privilege to other users.REVOKE SELECT ON TABLE sales.orders FROM alice CASCADE;: Automatically cascades the revocation to all downstream users who received the privilege from Alice.
Object Ownership Rules and Ownership Transfers
When an object (table, view, index, sequence) is created, the role that executed the CREATE statement is automatically designated as the OWNER of that object.
Ownership Privileges
The owner of an object enjoys special non-revocable rights:
- Can
ALTERthe object definition (add columns, rename tables, add constraints). - Can
DROPthe object. - Can
GRANTandREVOKEany privilege on the object to other roles. - Bypasses Row-Level Security (RLS) policies by default.
[!IMPORTANT] Only the Owner or Superuser: A user who has
ALL PRIVILEGESon a table still cannot drop or alter that table unless they are the table's owner or a superuser! Privileges grant data manipulation rights, not object lifecycle ownership.
Transferring Ownership
Ownership can be explicitly reassigned using ALTER ... OWNER TO:
ALTER TABLE sales.orders OWNER TO sales_admin;
ALTER SCHEMA sales OWNER TO sales_admin;
Dropping Roles That Own Objects
A role cannot be dropped if it owns objects or holds privileges:
-- Attempting to drop an active owner fails:
-- DROP ROLE dev_lead;
-- ERROR: role "dev_lead" cannot be dropped because some objects depend on it
-- Reassign all owned objects across the current database in one command
REASSIGN OWNED BY dev_lead TO new_owner;
-- Drop all remaining privilege grants held by dev_lead
DROP OWNED BY dev_lead;
-- Now the role can be dropped cleanly
DROP ROLE dev_lead;
Managing Future Privileges: ALTER DEFAULT PRIVILEGES
A critical challenge in production schema management is the "new table problem". Running GRANT SELECT ON ALL TABLES IN SCHEMA sales TO analyst; applies only to tables that exist at that exact instant. When an application deployment script creates a new table tomorrow, the analyst role receives permission denied.
To solve this, PostgreSQL provides ALTER DEFAULT PRIVILEGES:
-- Define default privileges for future tables
ALTER DEFAULT PRIVILEGES
FOR ROLE dev_deployer
IN SCHEMA sales
GRANT SELECT, INSERT ON TABLES TO reporting_role;
Syntax Mechanics and Best Practices
FOR ROLE creator_role: Specifies the role that will create future objects. If omitted, it defaults to the role executing theALTER DEFAULT PRIVILEGEScommand!IN SCHEMA schema_name: Restricts the rule to a specific schema. If omitted, the default privileges apply across the entire database whenevercreator_rolecreates an object.- In team environments where multiple developers create tables, the best practice is to assign ownership of the schema to a dedicated group role (e.g.,
schema_owner) and have developers executeSET ROLE schema_owner;prior to running migration scripts.
Row-Level Security (RLS) Fundamentals
While table privileges govern whether a user can access a table as a whole, Row-Level Security (RLS) restricts which individual rows a query can view or modify based on user identity or session context.
-- 1. Enable RLS on the table (Mandatory step)
ALTER TABLE accounts ENABLE ROW LEVEL SECURITY;
-- 2. Define a security policy for SELECT queries
CREATE POLICY user_account_policy ON accounts
FOR SELECT
TO application_user
USING (owner_role_name = CURRENT_USER);
-- 3. Define a security policy for INSERT/UPDATE validation
CREATE POLICY insert_account_policy ON accounts
FOR INSERT
TO application_user
WITH CHECK (department_id = 10);
Key Concepts of RLS
- Default-Deny Model: Once RLS is enabled on a table, non-owner users see zero rows by default until at least one policy is explicitly created that permits access.
USINGclause: Evaluates existing rows duringSELECT,UPDATE, andDELETE. Rows that evaluate tofalseorNULLare silently filtered out as if they did not exist.WITH CHECKclause: Evaluates new or modified rows duringINSERTandUPDATE. If the expression evaluates tofalseorNULL, the command aborts with an error.- Bypassing RLS: Table owners and superusers bypass RLS by default. To force RLS evaluation on the table owner as well, run:
ALTER TABLE accounts FORCE ROW LEVEL SECURITY;
Comparison: Role Attributes vs. Object Privileges
| Control Mechanism | Scope | Inheritance | Enforced By |
|---|---|---|---|
Role Attributes (SUPERUSER, CREATEDB) | Entire Cluster | Never Inherited | Engine core / postmaster |
Schema Privileges (USAGE, CREATE) | Specific Schema | Inherited via INHERIT | Namespace resolver |
Table Privileges (SELECT, INSERT) | Entire Table / Columns | Inherited via INHERIT | Query execution planner |
Row-Level Security (CREATE POLICY) | Individual Tuples / Rows | Applied to target roles | Query rewrite engine |
Exam Tips and Common Pitfalls
- Exam Trap: Role Attribute Inheritance: System attributes such as
SUPERUSER,CREATEDB, andCREATEROLEare never inherited through group membership. Even if user Bob is a member of groupdba_groupwhich hasCREATEDB, Bob cannot create a database unless Bob's own role hasCREATEDBor Bob runsSET ROLE dba_group. - Exam Trap: Dropping Tables vs. Table Privileges: Having
ALL PRIVILEGESon a table does NOT grant permission toDROP TABLEorALTER TABLE. Only the owner of the table or a superuser can drop or alter it. - Exam Trap: Default Privileges Target Creator: If an exam question asks why a new table is inaccessible despite running
ALTER DEFAULT PRIVILEGES ... GRANT SELECT ..., check the creator. If the command omittedFOR ROLE, it only applies when the administrator who ran the command creates tables, not when other developers create them. - Exam Trap: Schema USAGE Prerequisite: A query against
sales.customerswill fail with permission denied if the role lacksUSAGEon thesalesschema, even if grantedSELECTonsales.customers.
A database administrator configures access for an analytics group by running: GRANT USAGE ON SCHEMA analytics TO bi_users; and GRANT SELECT ON ALL TABLES IN SCHEMA analytics TO bi_users;. Two weeks later, a data engineer creates a new table named analytics.quarterly_churn. Members of bi_users report receiving: ERROR: permission denied for table quarterly_churn. What is the standard PostgreSQL solution to prevent this issue for future tables?
Role 'analyst_lead' has the NOINHERIT attribute. The role is granted membership in group 'financial_reporting', which possesses SELECT privileges on the ledger table. When analyst_lead connects and runs SELECT * FROM ledger;, what occurs?
A developer role possesses the following privileges: LOGIN, CREATEDB, and has been granted ALL PRIVILEGES on the inventory table inside schema store. However, the role has NOT been granted USAGE on schema store. What happens when the developer attempts to execute SELECT * FROM store.inventory;?