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.2

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.2
File Size Uploaded
pg_bloat_detective-0.1.2.tar.gz 18.8 kB Details

Built distribution (wheel)

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

Total release size: 34.3 kB

Release files / pg_bloat_detective-0.1.2.tar.gz

Download URL pg_bloat_detective-0.1.2.tar.gz
Size 18.8 kB
Tags Source
SHA-256 checksum
How to use checksums
975c27b1eed511786ce1ee3fc8f4924fd3a126fb5f2c5187931583b2693a01d6
BLAKE2b-256 checksum
How to use checksums
336193845f17f4e0f6fa143c1baa3a0371d864ee5bfb507b9c98f0ee01877990
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.2-py3-none-any.whl

Download URL pg_bloat_detective-0.1.2-py3-none-any.whl
Size 15.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
7883c8372fd2ae7e4eb1d8bcedbddfd65ea5592d7a40e73f5f573ff2f87674ef
BLAKE2b-256 checksum
How to use checksums
71695fb2462af00bb689b8f03266c88f94c543e7dab3097949508eedb1eeecfc
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

This release

0.1.2 This release

2 release files

0.1.1

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