Fix a finding
From finding to reviewed, reversible change: review, plan, apply, revert.
pgdba check prints remediation SQL for every finding. Two paths turn
that SQL into a change — direct per-action apply, or a generated fix
plan with recorded reverts — and both stay dry-run until you approve.
Review the finding
Findings are ranked by severity in the terminal plus
pgdba-report.md / pgdba-report.json. Drill into one before touching
anything:
pgdba why <finding-id> # plain-language explainer from the last report
Plan the change
pgdba fix <finding-id> reads the finding from the last report, builds
an ordered plan with a recorded revert for every statement, and writes
three artifacts:
pgdba check --dsn "$DATABASE_URL"
pgdba fix index.advisor
# fix plan for index.advisor: 1 statement(s), 1 with recorded reverts
# scripts: pgdba-fix-index.advisor.sql, pgdba-fix-index.advisor.revert.sql
pgdba-fix-<id>.sql— the executable statements in order, with preconditions (locks,CONCURRENTLYnotes) and blast-radius notes as comments.pgdba-fix-<id>.revert.sql— the mapped reverts in reverse order, withMANUAL STEPnotes where no mechanical revert exists.pgdba-fix-<id>.json— the machine-readable plan (statements, revert map, checksum for resume).
Without flags nothing executes — not even with a --dsn. Findings whose
remediation is prose (not mechanically executable SQL) produce a
guidance-only plan labeled manual fix, and --apply refuses them.
Apply it
Direct path — execute what you approve, per action:
pgdba check --apply # per-action prompts
pgdba check --apply --yes # blanket approval — requires --apply
pgdba check --apply --only connection.max_connections
Plan path — execute a reviewed fix plan:
pgdba fix index.advisor --apply --yes --dsn "$DATABASE_URL"
# fix applied 1 statement(s) for index.advisor
The gates, in order:
- Findings are ranked by severity; you select which to apply (or approve
all with
--yes). - A blast-radius warning shows the action count plus every HIGH-risk action’s remediation line before anything runs.
- Per-action confirm unless
--yes. On a non-TTY run,--applywithout--yesis refused — the report is still written (the refusal is recorded in the audit log), and the exit is 1. - Every action is audited: the report’s audit log records
applied,skipped,failed, andretryingrows with attempts, in execution order.
The plan path runs through the same safety layer (per-statement gating,
pooled-target direct-DSN bypass, audit rows) and records applied tags
in the audit journal. Without --yes, a TTY gets per-action confirms
and a non-TTY aborts. Interrupted applies resume: already-applied
statements are skipped on re-run.
Config-class findings (configuration duty) execute through the same
shared layer — there is no separate config-apply path — with reload
notes (SELECT pg_reload_conf() vs restart) in the preconditions;
cross-check pgdba config proposals before changing values by hand.
Hard limits
- RDS/replica targets refuse writes per finding (reported in the audit log).
- Multi-statement remediation stays dry-run for manual review.
- Deadlocked or serialization-failed statements retry up to 2 times.
- Nothing writes without
--apply; cron must never pass it.
Danger
--apply --yes executes every selected action with no per-action confirm.
Review the plan first; prefer per-action prompts outside maintenance
windows.
Revert it
pgdba fix index.advisor --revert --yes --dsn "$DATABASE_URL"
# fix reverted 1 statement(s) for index.advisor
Reverts run the mapped .revert.sql statements in reverse order. Check
the file for MANUAL STEP notes first — those need your hands, not the
tool’s.