Спроектировать метод списка с фильтрами, сортировкой и пагинацией и отличить изменение контракта, совместимое с клиентами, от ломающего, которое требует новой версии.
Длинные списки и долгая жизнь 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 в ответе: оно ломает клиентов, не готовых к незнакомым значениям. Поэтому в контракте заранее пишут, что клиент делает с неизвестным статусом, а новые значения анонсируют.