Pepelen
← Системный анализ: API, интеграции и данные

Урок

Списки и развитие API: пагинация, фильтры, версии

Спроектировать метод списка с фильтрами, сортировкой и пагинацией и отличить изменение контракта, совместимое с клиентами, от ломающего, которое требует новой версии.

1 / 7

Длинные списки и долгая жизнь API

Длинные списки и долгая жизнь API

Тысячи заказов одним ответом не отдают — список режут на страницы. Offset/limit (?limit=20&offset=40) прост, можно прыгнуть на любую страницу. Но новые записи между запросами сдвигают строки — на следующей странице дубли или пропуски, а большой offset дорог для базы. Курсор (?limit=20&cursor=…): сервер отдаёт nextCursor — метку вроде «после заказа 103», и следующая страница начинается после неё. Новые записи страницы не сдвигают, запрос быстрый, но на страницу 37 не прыгнуть. Для лент и выгрузок выбирают курсор. Всегда нужны предел limit (у «Ромашки» — 100) и явная сортировка, иначе страницы неустойчивы. Фильтры и сортировка — тоже параметры: ?status=delivered&createdFrom=2026-10-01&sort=-createdAt — доставленные (delivered) с 1 октября, минус — «по убыванию». Ответ — {"items": […], "nextCursor": "…"}; нет nextCursor — страниц больше нет. Клиенты API обновляются не сразу. Они — «терпимые читатели»: незнакомые поля игнорируют, поэтому совместимы новые необязательные поля и параметры, новые методы. Ломающее изменение выпускают только в новой версии (/v2), а старую поддерживают до объявленной даты и сообщают о ней заголовками Deprecation (RFC 9745) и Sunset (RFC 8594). Особый случай — новое значение enum в ответе: оно ломает клиентов, не готовых к незнакомым значениям. Поэтому в контракте заранее пишут, что клиент делает с неизвестным статусом, а новые значения анонсируют.
Ломает или нет
ИзменениеСовместимо?Почему
новое необязательное поле в ответедастарые клиенты его не читают
новый необязательный query-параметрдабез него поведение прежнее
новый методдастарые вызовы не меняются
удалить или переименовать поленетклиенты ищут старое имя
сменить тип поля, например число → строканетразбор ответа падает
сделать поле запроса обязательнымнетстарые запросы без поля получат ошибку
сменить смысл кода или статусанетклиент реагирует по-старому
Конспект урока
Длинные списки и долгая жизнь API
Тысячи заказов одним ответом не отдают — список режут на страницы. Offset/limit (?limit=20&offset=40) прост, можно прыгнуть на любую страницу. Но новые записи между запросами сдвигают строки — на следующей странице дубли или пропуски, а большой offset дорог для базы. Курсор (?limit=20&cursor=…): сервер отдаёт nextCursor — метку вроде «после заказа 103», и следующая страница начинается после неё. Новые записи страницы не сдвигают, запрос быстрый, но на страницу 37 не прыгнуть. Для лент и выгрузок выбирают курсор. Всегда нужны предел limit (у «Ромашки» — 100) и явная сортировка, иначе страницы неустойчивы. Фильтры и сортировка — тоже параметры: ?status=delivered&createdFrom=2026-10-01&sort=-createdAt — доставленные (delivered) с 1 октября, минус — «по убыванию». Ответ — {"items": […], "nextCursor": "…"}; нет nextCursor — страниц больше нет. Клиенты API обновляются не сразу. Они — «терпимые читатели»: незнакомые поля игнорируют, поэтому совместимы новые необязательные поля и параметры, новые методы. Ломающее изменение выпускают только в новой версии (/v2), а старую поддерживают до объявленной даты и сообщают о ней заголовками Deprecation (RFC 9745) и Sunset (RFC 8594). Особый случай — новое значение enum в ответе: оно ломает клиентов, не готовых к незнакомым значениям. Поэтому в контракте заранее пишут, что клиент делает с неизвестным статусом, а новые значения анонсируют.