Privilege Analysis
The Privileges tab compares what each user is granted with what they’ve actually used, and flags over-provisioned roles — granted privileges with no recorded usage. It’s the fastest way to act on least-privilege before an audit.
Requirements
The analysis reads usage counts from the pg_stat_statements extension. If it isn’t installed,
the tab says so and offers an Enable Extension button, which runs
CREATE EXTENSION IF NOT EXISTS pg_stat_statements; (your database user needs rights to create
extensions, and most servers also need pg_stat_statements in shared_preload_libraries, which
requires a restart — manual instructions are shown in the tab).
Running an analysis
Click Run Analysis (later, Re-run). Summary pills show total users, over-provisioned users, users with no usage data, and total unused privileges. Results group into:
- Over-Provisioned — users holding privileges with zero recorded calls.
- No Usage Data — users with no captured statements; usage can’t be determined, so nothing is flagged.
- Privileges Match Usage — nothing to do.
- Superusers — skipped: superusers bypass privilege checks, so grant analysis doesn’t apply.
Each user row shows their privilege chips marked ✓ (granted and used) or ✗ (granted, no recorded calls), plus call counts per statement type and total execution time.
How to read the results — honest caveats
- Usage is cumulative since
pg_stat_statementswas last reset. On a freshly enabled extension or a recently reset server, “unused” mostly means “not used yet” — let it collect over a representative period before revoking. - Classification is per user, by statement type (SELECT/INSERT/UPDATE/DELETE), not per schema or per table. A user flagged as using SELECT used it somewhere, not necessarily everywhere it’s granted.
- The DROP privilege (schema
CREATE— see Managing Users) is never flagged unused, because DDL isn’t captured by this analysis.
Revoking unused privileges
Revoke Unused on an over-provisioned row immediately executes real REVOKE statements for
each flagged privilege, across every non-system schema — there is no preview step and no
confirmation dialog, so treat the button as live. Each (schema, privilege) revoke is written to
the audit log individually; if one fails, the run stops there and the
revokes already executed stay applied.
As a guardrail, the button refuses to strip every privilege a user holds — for that, edit the user directly in the Users tab, which also gives you per-schema control.
Exporting
Export CSV saves the analysis (one row per user: status, granted / used / unused privileges,
and per-statement-type call counts) as privilege-analysis-YYYY-MM-DD.csv — handy as evidence of
a least-privilege review.