intermediate
Pagination, filtering, and sorting
Проектируйте stable list endpoints с cursor или offset pagination, bounded filters, deterministic sorting и clear metadata.
List endpoints нуждаются в стабильных контрактах: ограниченный размер страницы, детерминированная сортировка, явные фильтры и metadata для sync и UI.
**Offset pagination** — просто, но «плывёт» при concurrent writes:
GET /products?limit=20&offset=40&sort=-createdAt&category=shoes
Metadata ответа: `{ items, total, limit, offset }`.
**Cursor pagination** — стабильнее при churn; непрозрачный cursor (часто sort key + id):
GET /products?limit=20&cursor=eyJjcmVhdGVkQXQiOi4uLn0&sort=-createdAt
Ответ: `{ items, nextCursor, hasMore }`. Не раскрывайте внутренние offset в cursor.
Правила фильтрации:
- Whitelist полей и операторов (`status=eq:open`, `price=lte:100`).
- Ограничьте `limit` (например max 100).
- Документируйте default sort, если не передан.
На интервью: offset vs cursor для live feeds, tie-breaker при sort, почему неиндексированные фильтры бьют по production.
Типовые ошибки: неограниченный page size, sort без индекса, фильтры с full table scan, cursor с PII или внутренними id без подписи.
Компромисс: сложность cursor против UX offset (переход на страницу N). Гибрид: cursor для API, offset только для небольших admin datasets.
Чеклист:
- max limit на сервере.
- Детерминированный sort с tie-breaker.
- Whitelist фильтров; явный reject или согласованный ignore неизвестных params.
- Стабильная форма pagination metadata.