Paginação¶
Paginação retorna um conjunto grande e ordenado em páginas limitadas. É contrato de consistência, além de formato de resposta. Toda abordagem exige ordem determinística, normalmente com desempate único.
Offset, keyset e cursor¶
| Abordagem | Requisição | Vantagem | Compromisso |
|---|---|---|---|
| Offset | limit e offset ou página |
Acesso aleatório e UI simples | Varreduras profundas e deslocamentos sob escritas |
| Keyset | Últimos valores ordenados | Continuação eficiente por índice | Sem salto arbitrário; predicado segue a ordem |
| Cursor opaco | Token definido pelo servidor | Oculta estado composto e pode evoluir | Exige integridade, expiração e compatibilidade |
Para (created_at DESC, id DESC), o predicado é conceitualmente:
WHERE (created_at, id) < (:last_created_at, :last_id)
ORDER BY created_at DESC, id DESC
LIMIT :page_size
Sintaxe e suporte dependem do banco. Sem id único, timestamps iguais causam duplicações ou omissões.
Consistência sob mudanças¶
Offset se refere a posições; inserções e remoções deslocam resultados. Keyset continua em relação a valores e costuma ser mais estável, mas alterações nos campos de ordem ainda movem registros. Percurso point-in-time real exige snapshot ou versão, possivelmente caros.
O cursor deve ser opaco, protegido contra adulteração, vinculado a filtros e ordem e possuir expiração. Nunca inclua dados sensíveis sem proteção.
Regras da API e do banco¶
- limite o tamanho e rejeite valores inválidos;
- documente ordem padrão e continuação;
- filtre e pagine no armazenamento, não após carregar tudo;
- selecione colunas necessárias e confirme o índice;
- não prometa contagem exata quando seu custo for proibitivo;
- represente o próximo cursor independentemente da identidade interna.
Teste empates, páginas vazias e finais, âncoras removidas, inserções concorrentes, filtros alterados, cursor inválido e tamanho máximo. Inspecione plano e latência em posições profundas.