Stop bad PostgreSQL indexes before they reach production
Project description
IndexPilot
Stop bad PostgreSQL indexes before they reach production
Check the exact CREATE INDEX in a migration against the workload your database actually runs.
IndexPilot is a read-only PostgreSQL review CLI. It combines aggregate pg_stat_statements
evidence, comparable existing indexes, and optional HypoPG plans, then writes a cautious verdict
with Markdown, JSON, and optional SARIF evidence for the pull request.
Use it to answer practical questions:
- Should I add this PostgreSQL index?
- Does this migration add a duplicate index?
- Why might PostgreSQL ignore this index?
- How can I test an index before creating it?
- How do I review index migrations in CI?
Advisory only. IndexPilot never applies the migration or creates a physical index. A positive result means “benchmark this next,” not “ship this automatically.”
Website · Quick start · Local dashboard · Installation · Documentation · GitHub Action
Try it in 60 seconds
This database-free example proves the install and review path before you configure PostgreSQL:
git clone https://github.com/eyeinthesky6/indexpilot.git
cd indexpilot
uvx --from "indexpilot==1.1.0a6" indexpilot review --migration-file examples/quickstart/migration.sql --snapshot-file examples/quickstart/workload-snapshot.json --output artifacts/first-review.json --markdown-output artifacts/first-review.md --stdout
Expected result:
Index statements reviewed: 1
Verdicts: {'existing_overlap': 1}
The example catches a proposed (tenant_id, created_at) index already covered by the sanitized
catalog. No database, credentials, Docker, or extension is used. See the
installation guide if
uvx is unavailable.
Review your migration
1. Install
pipx install "indexpilot==1.1.0a6"
indexpilot --version
2. Provide a read-only PostgreSQL connection
export DB_HOST=database.example.com
export DB_PORT=5432
export DB_NAME=my_app
export DB_USER=indexpilot_reader
export DB_PASSWORD='replace-me'
export DB_SSLMODE=require
The database needs pg_stat_statements. IndexPilot does not need CREATE, table writes, or
ownership.
3. Check readiness
indexpilot doctor --schema public --min-calls 10
4. Review the migration
indexpilot review \
--migration-file migrations/add_orders_index.sql \
--output artifacts/indexpilot.json \
--markdown-output artifacts/indexpilot.md \
--sarif-output artifacts/indexpilot.sarif
This first pass catches overlap and missing evidence. Add --hypopg when doctor confirms a
compatible PostgreSQL 16+ database and an installed HypoPG extension.
Open the local dashboard
Install the optional API support, then start the packaged UI and API together:
pipx install "indexpilot[api]==1.1.0a6"
indexpilot dashboard
The command selects a free local port, opens /dashboard/ in your browser, and stops when you
press Ctrl+C. It needs no Node.js process and no login because it binds only to 127.0.0.1.
If PostgreSQL is not configured yet, the dashboard stays open and shows the missing connection.
Use indexpilot api with explicit bearer-token authentication for any non-loopback API bind.
For CI, the composite GitHub Action supports protected live review and database-free snapshot review. Fork workflows must load snapshot evidence from the trusted base commit, never from the contributor checkout; follow the fork-safe workflow.
How it fits with your existing tools
IndexPilot accepts an ordinary SQL migration file, so a human, coding agent, or index adviser can propose the index. It then leaves standard report artifacts for CI and reviewers.
flowchart LR
P["Human · coding agent · index adviser"] --> M["CREATE INDEX migration"]
M --> S["Migration safety checks"]
M --> I["IndexPilot workload evidence"]
I -. "optional" .-> H["HypoPG planner check"]
I --> R["Review decision"]
R --> B["Production-copy benchmark"]
| Tool or step | What it contributes |
|---|---|
| Squawk or another migration linter | Checks whether the DDL is operationally safe |
| Dexter, an adviser, a developer, or an agent | Proposes a candidate index |
| IndexPilot | Checks whether that exact proposal has workload and overlap evidence |
| HypoPG | Provides the optional session-local hypothetical index mechanism |
| pgbench or your load test | Measures real latency, writes, size, and rollback before release |
These tools are complementary. IndexPilot does not automatically call every tool in the table; its simple boundary is the migration SQL in and portable evidence out. See the tool-fit guide for details.
How it works
- Parse locally. SQLGlot reads the PostgreSQL index proposal without executing it.
- Read evidence. IndexPilot collects aggregate workload patterns and comparable catalog indexes.
- Check the planner when requested. HypoPG and
EXPLAIN, neverEXPLAIN ANALYZE, test a session-local hypothetical shape. - Leave a decision record. Each proposal receives a bounded verdict, evidence, limits, and next step.
The main verdicts are worth_benchmarking, existing_overlap,
not_supported_by_current_planner_evidence, and inconclusive. Their exact meaning and exit-code
behavior are documented in the usage guide.
Safety boundary
- The public review path is read-only and never creates, drops, or reindexes a physical index.
- It runs
EXPLAIN, neverEXPLAIN ANALYZE. - Reports contain query fingerprints rather than raw workload SQL.
- Planner cost is not measured production latency, and overlap is not automatic drop advice.
- Generated reports still contain object names and aggregate metadata; review them before sharing.
Documentation
| Guide | Use it for |
|---|---|
| Documentation hub | Find the supported public documentation |
| Installation | Python, PostgreSQL access, pg_stat_statements, and optional HypoPG |
| CLI usage | Commands, verdicts, syntax, outputs, privacy, and tool fit |
| Trusted CI | Protected live review and database-free fork review |
| Security | Credential, disclosure, and API boundaries |
| Roadmap and limits | Deferred evidence and compatibility work |
| Agent skill | Let a compatible coding agent install, test, and report the first result |
Help and contribute
- After the first successful interactive review, IndexPilot prints one optional community link. It
does not open the network or collect telemetry, never runs in CI or
--stdoutoutput, and can be disabled withINDEXPILOT_NO_COMMUNITY_PROMPT=1. - Ask setup questions in Q&A Discussions.
- Share an idea in Ideas Discussions.
- Report a reproducible problem through the issue forms.
- Start contributing with good first issues and CONTRIBUTING.md.
- If your team reviews index migrations repeatedly, share that workflow pain or read the Team workflow preview.
License
IndexPilot is available under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file indexpilot-1.1.0a6.tar.gz.
File metadata
- Download URL: indexpilot-1.1.0a6.tar.gz
- Upload date:
- Size: 1.5 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fdde683ef95cc2bf5eb04e43cef9a5a17dac7179326c2a3236af7140780c953a
|
|
| MD5 |
bd975695ad0560d633c87e89309f8e93
|
|
| BLAKE2b-256 |
7fb41647df1b21fa4bcc431c89d6c60553aed4920936041ae17ab98cca7ed8ec
|
Provenance
The following attestation bundles were made for indexpilot-1.1.0a6.tar.gz:
Publisher:
publish.yml on eyeinthesky6/indexpilot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
indexpilot-1.1.0a6.tar.gz -
Subject digest:
fdde683ef95cc2bf5eb04e43cef9a5a17dac7179326c2a3236af7140780c953a - Sigstore transparency entry: 2188630616
- Sigstore integration time:
-
Permalink:
eyeinthesky6/indexpilot@7d92b62e5725dee6ecaf03d945a1a7d1460b0ceb -
Branch / Tag:
refs/tags/v1.1.0a6 - Owner: https://github.com/eyeinthesky6
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7d92b62e5725dee6ecaf03d945a1a7d1460b0ceb -
Trigger Event:
release
-
Statement type:
File details
Details for the file indexpilot-1.1.0a6-py3-none-any.whl.
File metadata
- Download URL: indexpilot-1.1.0a6-py3-none-any.whl
- Upload date:
- Size: 1.6 MB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
62251dcd265d7c651862249aff8d63bb38b0e2305d7ce6ebb457f8f73286ad44
|
|
| MD5 |
439df1c663c1b1cfd90b5ea35971406b
|
|
| BLAKE2b-256 |
6562c9061739a0a47a29bb8efe435748acae19186038b7e76f29aaf7c158a997
|
Provenance
The following attestation bundles were made for indexpilot-1.1.0a6-py3-none-any.whl:
Publisher:
publish.yml on eyeinthesky6/indexpilot
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
indexpilot-1.1.0a6-py3-none-any.whl -
Subject digest:
62251dcd265d7c651862249aff8d63bb38b0e2305d7ce6ebb457f8f73286ad44 - Sigstore transparency entry: 2188630662
- Sigstore integration time:
-
Permalink:
eyeinthesky6/indexpilot@7d92b62e5725dee6ecaf03d945a1a7d1460b0ceb -
Branch / Tag:
refs/tags/v1.1.0a6 - Owner: https://github.com/eyeinthesky6
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7d92b62e5725dee6ecaf03d945a1a7d1460b0ceb -
Trigger Event:
release
-
Statement type: