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.