---
id: design-indexes
agent: data-engineer
title: Desenhar a estratégia de índices
inputs: [schema, padrões de acesso (do modelo de domínio)]
outputs: [DDL de índices, docs/data/indexes.md]
elicit: false
modes: [interactive, yolo]
---

# Desenhar a estratégia de índices

**Objetivo:** criar índices guiados por padrão de acesso real — cada índice serve a uma query que
existe. Índice sem query que o justifique é peso morto; FK sem índice é débito.

**Pré-condições:**
- O schema existe (saída de `create-schema`).
- Os padrões de acesso estão documentados no modelo de domínio (quais queries, por qual chave, com
  qual frequência). Se faltam, **pare** — índice sem padrão de acesso é palpite, e eu não otimizo por
  palpite.

## Passos

1. **Releia os padrões de acesso** do modelo de domínio. Liste as queries quentes: filtros, ordenações,
   joins frequentes. Cada índice que eu criar vai apontar para uma dessas queries.
2. **Indexe toda foreign key** que participa de join ou filtro. FK sem índice é a causa silenciosa de
   query lenta — eu sinalizo e cubro.
3. **Crie índices compostos na ordem certa de colunas** (igualdade antes de range), casando com os
   filtros `WHERE`/`ORDER BY` reais. Coluna na ordem errada é índice que o planner ignora.
4. **Considere índices especializados quando o acesso justifica:** parcial (`WHERE deleted_at IS
   NULL`), `GIN`/`GIN trgm` para busca textual/JSONB, `UNIQUE` para identidade de negócio. Cada um
   com a query que o motiva anotada.
5. **Evite over-indexing.** Todo índice custa em escrita e espaço. Não crio índice "por garantia" — se
   não há query, não há índice.
6. **Escreva DDL idempotente** com `CREATE INDEX IF NOT EXISTS` e, em produção, `CREATE INDEX
   CONCURRENTLY` para não travar a tabela. Isso vai virar migration via `create-migration-plan`.
7. **Valide com evidência, não intuição:** rode `EXPLAIN (ANALYZE)` (ou a task `analyze-performance`)
   na query alvo antes/depois para confirmar que o índice é usado e melhora o plano. Decisão de
   performance vem de medição.
8. **Documente em `docs/data/indexes.md`:** cada índice, a query que o justifica e a evidência do
   explain plan.

## Critério de pronto (DoD)

- [ ] Cada índice rastreia a uma query/padrão de acesso documentado
- [ ] Toda FK que participa de join/filtro está indexada
- [ ] Índices compostos com ordem de coluna correta
- [ ] Sem over-indexing (nenhum índice sem query que o justifique)
- [ ] DDL idempotente (`IF NOT EXISTS`, `CONCURRENTLY` em produção)
- [ ] Uso e ganho confirmados por `EXPLAIN ANALYZE`
- [ ] `docs/data/indexes.md` escrito com a evidência

## Falha / recuperação

- **Padrões de acesso ausentes** → volto a `db-domain-modeling`; não crio índice no escuro.
- **`EXPLAIN` mostra que o índice não é usado** → reviso ordem de colunas/tipo do índice em vez de
  empilhar índices; índice que o planner ignora é só custo.
- **A indexação vira parte de uma migration** → encaminho para `create-migration-plan`; aplicação em
  ambiente remoto é delegada ao @devops, eu não dou push.
