Skip to main content

pg-bloat-detective

Read-only Postgres bloat detective: cheap timeline, named blocker, index bloat, evidence-linked report, before/after proof.

Quickstart

docker compose up -d
pip install -e ".[dev]"
python -m bloatdetective collect --db timeline.db   # snapshot prod (read-only)
python workload/churn.py --mode idle-xact --secs 60 &  # create the failure
python -m bloatdetective collect --db timeline.db
python -m bloatdetective report --db timeline.db --html --out report.html
python -m bloatdetective serve --db timeline.db &   # :9187/metrics for Prometheus
pytest
bash scripts/benchmark.sh   # full before/after proof -> REPORT.md

Verdicts

Heap: normal (steady-state, leave alone) · vacuum-starved · blocked-by-idle-xact|slot|prepared|active-xact · needs-rewrite. Index: index-bloated (pgstatindex bloat >30% → needs REINDEX, VACUUM can't fix it) · index-unused (idx_scan=0 across snapshots → DROP candidate).

Index bloat is the differentiator (pganalyze admits the gap): collect runs exact pgstatindex only on indexes under the 1GB cost guard (--max-bytes tunes it, --allow-large overrides), metric = 100 − avg_leaf_density. Exported as pgbloat_index_bloat_pct / pgbloat_index_scans, charted in the shadcn dashboard, Graphed in Grafana.

Benchmark (measured 2026-10-05, local PG16 — heap + index, live run just now)

30s churn, no blocker (autovacuum simply lost) → VACUUM ANALYZE + REINDEX:

moment pg_stat dead approx dead% index bloat% (density) verdict
before fix 5,108,201 — (single-snapshot lag) 41.9% vacuum-starved + index-bloated churn_pkey
after fix 0 0.0% 9.9% normal — steady state, leave alone

Earlier hole, now closed: an index at 83.7% bloat (density 16.3) dropped to 9.9% (density 90.1) after REINDEX — VACUUM alone never touches that. Full log in REPORT.md, visual in report.html.

See PLAN.md for the detailed 3-week plan + competitor gap.

MCP server (Claude Desktop / Cursor / any MCP client)

5 tools, read-only on Postgres (5s statement timeout, read-only tx). bloat_check returns verdict + evidence + fix per table/index; bloat_live_diagnose snapshots a throwaway DB so your timeline file is never touched — safest for prod DSNs.

pip install -e .   # pulls mcp + psycopg
bloat-mcp          # stdio transport

Claude Desktop (~/Library/Application Support/Claude/claude_desktop_config.json):

{"mcpServers": {"bloat-detective": {
  "command": "/abs/path/pg-bloat-detective/.venv/bin/python",
  "args": ["-m", "bloatdetective.mcp_server"],
  "env": {"BLOAT_DSN": "dbname=bloatdemo user=postgres host=localhost port=5433",
          "BLOAT_DB": "/abs/path/pg-bloat-detective/timeline.db"}}}}
tool what the agent gets
bloat_check verdicts + evidence + action per table/index
bloat_collect snapshot timeline, return fresh verdicts
bloat_timeline dead/approx/index-bloat series — when it started
bloat_blockers pid + query + xmin age + slot — who to kill
bloat_live_diagnose one-shot throwaway snapshot, diagnose, discard

Public listing: mcp.so + PulseMCP accept GitHub submissions (server.json + README badge) — repo is ready, submit the URL after push.

Metadata

Release files for pg-bloat-detective 0.1.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pg-bloat-detective 0.1.1
File Size Uploaded
pg_bloat_detective-0.1.1.tar.gz 18.8 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pg-bloat-detective 0.1.1
File Interpreter ABI Platform
pg_bloat_detective-0.1.1-py3-none-any.whl Python 3 none any Details

Total release size: 34.2 kB

Release files / pg_bloat_detective-0.1.1.tar.gz

Download URL pg_bloat_detective-0.1.1.tar.gz
Size 18.8 kB
Tags Source
SHA-256 checksum
How to use checksums
7465a7b08e864c95f9fc86392dafbff27d76ac078a254d235b58c77d1243f2ef
BLAKE2b-256 checksum
How to use checksums
88f4efd58fbed361597757212d4061e2f77160a472ae4445da0879139df994f2
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release files / pg_bloat_detective-0.1.1-py3-none-any.whl

Download URL pg_bloat_detective-0.1.1-py3-none-any.whl
Size 15.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
6db504c567a7db958834d3d5e868e199f209d792342b953fb0948222b0223cf8
BLAKE2b-256 checksum
How to use checksums
b4752614f4cfd4e2bd0d8226472bb48dfa251b1477edabe9c72b93b82af3c9f8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 7, 2026.

Transparency log

Release history Release notifications | RSS feed

0.1.3

2 release files

0.1.2

2 release files

This release

0.1.1 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page