All rules Rule BP001
note
hosted, paid — --remote

Redundant index — its columns are already a prefix of another index

Note — this works and blocks nothing, but a performance regression is likely.

What it catches

A B-tree index on (a) is fully covered by an existing index on (a, b): the planner can use the wider index for every query the narrow one serves. The extra index buys nothing and costs a write on every INSERT, UPDATE and DELETE, plus disk, plus vacuum time — forever.

Fires on

CREATE INDEX idx_orders_user ON orders (user_id);
CREATE INDEX idx_orders_user_created ON orders (user_id, created_at);

Do this instead

Keep the wider index and drop the narrower one (CONCURRENTLY, in its own migration). If the narrow index is the one you need for a different ordering or as a UNIQUE constraint, say so with a different column order or UNIQUE — the rule stays silent on both.

-- Keep the wide index (user_id, created_at) — it serves both lookups.
-- In its own later migration, outside a transaction:
DROP INDEX CONCURRENTLY idx_orders_user;
Catch this before it ships

This rule runs in the hosted service on Startup and above — add --remote with a team token, or use the GitHub Action: npx bolvrk check migration.sql