Postgres Index Bloat and REINDEX CONCURRENTLY Strategy Prompt
Turn raw index-bloat and usage stats into a ranked, safe REINDEX/DROP plan — so you reclaim space and restore performance without taking an outage or dropping an index something silently depends on.
- Target user
- DBAs and platform engineers reclaiming space from bloated Postgres indexes
- Difficulty
- Advanced
- Tools
- Claude, ChatGPT, Cursor
The prompt
You are a senior PostgreSQL DBA who maintains large OLTP databases where indexes slowly bloat from churn (updates and deletes leaving dead tuples) and where a careless REINDEX can cause a lock storm. You plan maintenance from evidence — bloat estimates, index size, scan counts, and duplicate/redundant index detection — never from a hunch. I will paste: - Postgres major version (matters: REINDEX CONCURRENTLY needs 12+): [VERSION] - Index bloat estimate output (from pgstattuple or a bloat-estimate query): [BLOAT DATA] - Index usage from pg_stat_user_indexes (idx_scan, idx_tup_read): [USAGE DATA] - Index definitions and sizes (pg_indexes + pg_relation_size): [INDEX DEFS] - Maintenance window length and whether a replica exists: [CONSTRAINTS] Work through this in order: 1. **Classify each index** — bloated-but-used (REINDEX candidate), unused (idx_scan ~0 for a meaningful window, DROP candidate), redundant/duplicate (leading columns are a prefix of another index), or invalid (a failed prior CONCURRENTLY left `indisvalid = false`). Tie each verdict to specific numbers. 2. **Rank the work by payoff and risk** — biggest reclaimable bytes and highest write/read impact first, but flag anything that holds a lock or blocks writes. For each index give the estimated space reclaimed and why it bloated (high update churn, long-running transactions pinning dead tuples, disabled/starved autovacuum). 3. **Emit exact, safe commands** — prefer `REINDEX INDEX CONCURRENTLY` (no ACCESS EXCLUSIVE lock); note that it needs disk headroom for a full duplicate index and cannot run inside a transaction block. For unused indexes, `DROP INDEX CONCURRENTLY`. For duplicates, name which one to keep. Provide the cleanup for any leftover invalid `_ccnew` index. 4. **Give a verification step** — the query to confirm `indisvalid = true` after each REINDEX, the before/after `pg_relation_size`, and how to re-check bloat and idx_scan afterward. Output format: (a) one-line verdict on overall bloat, (b) a ranked table [index | verdict | reclaimable | action | risk], (c) the exact commands in run order, (d) the verification queries. Guardrails: never DROP an index on prod until idx_scan confirms it is unused over a full business cycle (including month-end/quarter-end jobs) and you have the CREATE statement saved to recreate it. REINDEX CONCURRENTLY needs free disk equal to the index size; check headroom first.
Run this prompt with AI
Test it, get an AI-improved version, or compare models — live in the Prompt Workspace. No copy-paste.
Why this prompt works
Index bloat is easy to misdiagnose. Size alone does not tell you whether an index is bloated, redundant, or simply large-because-the-table-is-large. This prompt forces a classification pass first — bloated-but-used, unused, redundant, or invalid — each tied to concrete numbers from pgstattuple and pg_stat_user_indexes, so the action list reflects reality rather than a fear of big numbers.
The ranking step keeps the work honest about trade-offs. Reclaiming the most bytes is not always the highest priority; an index that fronts a hot write path may bloat fastest but also be the riskiest to rebuild during peak hours. By pairing reclaimable space with lock and disk risk, the model proposes the smallest, safest sequence rather than a blanket “REINDEX everything.”
Finally, the guardrails encode the two ways this operation bites people: dropping an index that a rare-but-critical month-end job depends on, and starting a REINDEX CONCURRENTLY without the disk headroom it needs for a duplicate index — which fails partway and leaves an invalid _ccnew index behind. The verification step closes the loop by confirming indisvalid and measuring the actual space reclaimed.
Related prompts
-
Postgres VACUUM, Bloat & Autovacuum Tuning Prompt
Diagnose table and index bloat, decide between VACUUM, autovacuum tuning, and a rebuild, and produce per-table autovacuum settings — so dead tuples and wraparound risk stop quietly degrading your database.
-
Postgres BRIN Index Design for Time-Series Tables Prompt
Decide whether a BRIN index will actually speed up your large, naturally-ordered table — and size pages_per_range correctly — instead of blindly reaching for a B-tree that bloats storage on append-only data.
-
Postgres Keyset (Cursor) Pagination Optimization Prompt
Convert a slow OFFSET/LIMIT pagination query into stable keyset (seek) pagination that stays fast on deep pages — with a matching index and a correct tuple-comparison predicate, not a broken one-column WHERE.
-
Postgres HOT Update and Fillfactor Tuning Prompt
Diagnose why an update-heavy table bloats and burns write I/O despite autovacuum, then decide on fillfactor, index removal, and column changes to unlock Heap-Only Tuple (HOT) updates — cutting index write amplification and bloat at the source.
More Postgres prompts & error guides
Browse every Postgres prompt and troubleshooting guide in one place.
Reading prompts? Get all 500 in one free PDF
500 battle-tested, copy-paste AI prompts engineered by a senior systems engineer — every one with fill-in placeholders and safety/back-out notes. Drop your email and it's yours.
- 500 prompts: Linux · Kubernetes · Terraform · OpenStack · GitLab · Docker · Monitoring · Incident Response
- Instant PDF download — yours free, forever
- Plus one practical AI-workflow email a week (no spam)
Single opt-in · unsubscribe anytime · no spam.