Разработка платформы доставки: как построить масштабируемую инфраструктуру для ресторанов и ритейла

Разработка платформы доставки — это построение архитектуры, в которую заложено масштабирование. В этой статье мы разобрали все пять архитектурных слоёв, от которых зависит, будет платформа доставки работать под нагрузкой или сломается: маршрутизация и назначение курьеров, live трекинг, диспетчерские инструменты, интеграция с агрегаторами и offline-first подход. Мы пройдём по каждому слою — сразу для ресторанов и для ритейла, — опираясь на публичный промышленный эталон (инженерный разбор алгоритмов Яндекс Доставки) и на наши собственные проекты.

Почему платформа доставки ломается при росте нагрузки

Слой приёма заказов — простая часть. Экран оформления, платёжный провайдер, каталог — это базовые задачи, и грамотный MVP закрывает их за пару недель. Настоящая сложность начинается после нажатия «Оформить заказ»: именно здесь решается, кто повезёт заказ, синхронизируются ли все участники по поводу того, где он сейчас, и удержится ли система целой, когда курьер въезжает в мёртвую зону или в магазине падает интернет.

Эти механизмы редко проектируют заранее, потому что на малых объёмах они работают без сбоев. Диспетчер окидывает взглядом десяток открытых заказов и раздаёт их вручную. Пока пользователей сотня, опрос сервера каждые несколько секунд ради обновления статуса выглядит мгновенным. Один агрегатор нетрудно синхронизировать вручную. На масштабе каждая из этих мелочей примерно одновременно превращается в полноценную инженерную задачу. Поэтому growth-stage-команды в доставке чаще всего получают все эти проблемы одним пакетом — и сразу.

Скорее всего, вы уже почувствовали первый тревожный звонок: MVP собрала аутсорс-команда, работает правило «ближайший свободный курьер», логичное на старте, статус заказа обновляется поллингом (приложение периодически опрашивает сервер: «есть обновления?») — всё это ещё держится, но уже начинает захлёбываться. Дальше мы покажем, как выглядит зрелая версия каждого слоя и, что не менее важно, что действительно стоит строить на вашем этапе, а что может подождать.

Маршрутизация и назначение курьеров — что на самом деле решает, кто повезёт заказ

Назначение курьеров — это решающий узел платформы доставки: есть открытый заказ и пул курьеров (или точек сбора) — кто его берёт и в каком порядке? Ошибка на этом шаге бьёт в одну из двух сторон: курьер приезжает слишком рано и простаивает в ожидании готового заказа — или слишком поздно, и клиент получает остывшую еду. С ростом объёма добавляется батчинг: два-три заказа из одной кухни или соседних магазинов объединяют на одного курьера так, чтобы никто не выбился из срока доставки.

Здесь работает лестница зрелости — от ручного решения до алгоритмического, и важно понимать, на какой ступени вы находитесь.

Первая ступень — ручное или полуручное распределение заказов по карте. Человек смотрит на карту, видит, какие заказы географически близки, группирует их и отдаёт тому, кто следующий в очереди. Ровно так сегодня устроена доставка курьерами у Sizl, сети dark kitchen из Чикаго: на экране группировки сборщик видит рядом готовые заказы и свободных курьеров, по карте объединяет близкие адреса в один рейс и вручную назначает его курьеру. Автоматизацию этой группировки мы планируем позже — пока ручной шаг сделан осознанно, потому что он позволяет команде видеть, где реально возникают узкие места, прежде чем зашивать вокруг них правила.

Разработка платформы доставки: как построить масштабируемую инфраструктуру для ресторанов и ритейла

Вторая ступень — батчинг по правилам: то, что раньше решал человек на глаз, превращается в чёткие правила (одна кухня, в пределах X минут друг от друга, в радиусе Y метров, не больше Z заказов на рейс). Рутинные решения уходят от человека, а поведение системы остаётся предсказуемым и понятным. Батчинг стоит усилий, потому что напрямую бьёт в проблему «рано/поздно»: курьер, выехавший сразу с двумя заказами в один квартал, меньше простаивает и успевает больше доставок за час — при условии, что второй заказ не остынет, пока везут первый. Слишком агрессивное правило группировки — и небольшой выигрыш в маршруте оборачивается клиентом с еле тёплым пакетом. Поэтому переход на следующую ступень диктует математика: число заказов и их плотность.

Верхняя ступень — машинное обучение плюс оптимизация, и самый показательный публичный пример на русском рынке — разбор, который Яндекс Доставка опубликовала в своём инженерном блоге (статья руководителя R&D-службы эффективности доставки от 11 марта 2025 года). Это разбор промышленного масштаба, причём технически более глубокий, чем маркетинговые обзоры: для поиска ближайших курьеров используется k-d-дерево в реализации библиотеки nanoflann; реальное время в пути считается не по прямой, а по дорожному графу — алгоритмом Дейкстры через собственный Yandex Router API; глобально-оптимальное назначение и батчинг заказов решаются венгерским алгоритмом (задача о назначениях), который на больших объёмах может требовать порядка 10⁹ итераций, поэтому его отдельно оптимизируют; а вся система горизонтально масштабируется по географии — расчёты разбиваются на независимые сегменты (минимальный — городская агломерация), чтобы не считать заказы и курьеров из разных регионов вместе. Сама задача батчинга и маршрутизации имеет имя в литературе — Vehicle Routing Problem — и инструментарий настолько стандартный, что у Google есть готовая библиотека OR-Tools для маршрутизации, которая из коробки решает многоточечный батчинг с ограничениями по вместимости и временным окнам.

Нужная вам ступень зависит от плотности заказов и числа точек сбора. Ритейлер с собственной доставкой из нескольких магазинов и сеть ресторанов с несколькими кухнями решают одну и ту же задачу в одном порядке: начинать там, где уже есть объём, и подниматься на ступень выше только тогда, когда это оправдано цифрами.

Отслеживание заказа в реальном времени: сокеты вместо поллинга

Live трекинг обещает каждое приложение доставки. Реализуют его достойно куда реже. Самое частое упрощение — поллинг: клиент с фиксированным интервалом спрашивает у сервера «есть обновления?». На малом объёме это нормально. На масштабе — сажает батарею устройства, заваливает сервер запросами, которые в основном возвращают «ничего не изменилось», и всё равно отстаёт: обновление, которое вы видите, свежо ровно настолько, насколько свеж последний опрос.

Продакшн-приложения доставки вместо этого используют постоянное WebSocket-соединение и пушат изменения на клиент в момент, когда они происходят. Ably, инфраструктурный провайдер для realtime-систем, подробно разбирает техническое обоснование в своём сравнении long polling и WebSockets: постоянное соединение снижает задержку и нагрузку на сервер по сравнению с периодическим опросом по мере роста числа подключённых пользователей. Это преимущество работает в обе стороны трекинга — и при пуше изменений статуса заказа клиенту, и при трансляции live-геопозиции курьера на карту.

Live-статус заказа и карту с курьером мы реализовали на Yapoki — высоконагруженном приложении доставки еды (20k+ скачиваний, 200+ заказов в день, 35% от общего объёма заказов бренда): клиент видит статус и следит за приготовлением в реальном времени, а движение курьера отображается на карте и обновляется автоматически. В курьерском приложении Sizl геопозиция курьера так же синхронизируется с картой и обновляется автоматически, пока он в пути. Во всех этих проектах мы намеренно берём проверенные геосервисы: Mapbox, Google Maps и OpenStreetMap.

Разработка платформы доставки: как построить масштабируемую инфраструктуру для ресторанов и ритейла

В ритейле всё устроено так же. Покупателю, который ждёт доставку продуктов или лекарств день в день, нужен тот же live-статус и та же карта, что и клиенту ресторана, — и обслуживает их одна и та же сокет-архитектура.

Диспетчерская панель: как персонал управляет заказами

Почти вся дизайнерская энергия в продукте доставки уходит в клиентское приложение — ту часть, которую видят инвесторы и клиенты. Диспетчерская и операционная панель — интерфейс, которым реально пользуется менеджер точки или руководитель операций, — строится обычно последней и по остаточному принципу. Такой порядок приоритетов вывернут наизнанку, потому что именно ops-панель определяет, приедет заказ вовремя или нет.

Админ-панель курьерского приложения Sizl — конкретный пример того, как этот слой выглядит в проде. Заказ движется по видимому конвейеру: подтверждён → готовится → сборка рейса → передан курьеру. Когда курьер доезжает до точки, он нажимает «Готов ехать», и это переключает его статус в панели, так что сборщик знает, кто следующий в очереди. Сборщик формирует рейс и отдаёт его курьеру. Весь смысл в том, что никто ничего не угадывает: кухня, сборщик и курьер смотрят на одно и то же актуальное состояние.

Разработка платформы доставки: как построить масштабируемую инфраструктуру для ресторанов и ритейла

Как уже сказано в разделе про назначение курьеров, сборка рейса здесь — ручная операция: сборщик группирует близкие заказы по карте, а автоматизация этого шага лежит в бэклоге.

В рознице всё то же самое: сотрудники магазина видят очередь заказов в панели, отмечают готовые и передают их курьеру.

Интеграция с агрегаторами: единое меню на всех площадках

Большинство ресторанов и многие ритейлеры продают не через один канал. Они держат собственное приложение и размещаются на агрегаторах — Wolt, Glovo, Яндекс Еда, Купер. Техническая ловушка в том, что у каждой площадки своя модель интеграции. Одни пушат события заказа вам через вебхуки; другие ждут, что вы будете опрашивать их сами. Обновления меню и каталога расходятся по разным площадкам с разной частотой. Без управления этим возникает рассинхрон: позиция, помеченная как отсутствующая в вашем POS, всё ещё доступна к заказу на одной площадке; новая цена обновилась на двух площадках, а на третьей осталась старая; и клиент заказывает то, что вы не можете отдать.

Решение — отдельный слой управления меню и каталогом. Он стоит над вашим POS или товарным каталогом и сам поддерживает актуальные данные во всех каналах продаж, вместо того чтобы синхронизировать каждый вручную. Принцип одинаков и для ресторанных агрегаторов, и для ритейл-маркетплейсов.

Здесь стоит заранее заложить в архитектуру две вещи.

Первая — как приходят заказы. Одни площадки присылают их через вебхуки, сразу в момент оформления: ваша сторона должна надёжно принять заказ, подтвердить его и при сбое повторить попытку. Другие работают по поллингу — новые заказы нужно самому запрашивать по расписанию, а значит, на вас ложится частота опроса и защита от дублей.

Вторая — частота обновлений. Наличие товаров и цены расходятся по площадкам с разной скоростью: отметка «нет в наличии» может сработать мгновенно на одной площадке и запоздать на другой.

Слой управления снимает обе проблемы: у вас одно внутреннее представление каталога, одно место, где определяется, что считать «доступным», и отдельные адаптеры под каждый канал, которые приводят эти данные к формату и срокам конкретной площадки. Для ритейлера с тысячами SKU на нескольких маркетплейсах именно такая нормализация отделяет спокойную автоматическую сверку от ручной чистки таблиц каждый вечер.

Для самой физической доставки есть параллельный паттерн интеграции, который стоит знать. Вместо найма курьерского парка мерчант может обращаться к внешнему логистическому сервису по API. У Яндекс Доставки есть логистический API для бизнеса: запрос курьера одним API-вызовом, без собственного штата, — и это подходит не только ресторанам, но и аптекам, магазинам и ритейлу. Мы обычно закрываем этот слой одной платформой оркестрации доставки, а не подключаем каждого логистического партнёра по отдельности. Так с ростом числа каналов интеграция не разрастается.

Offline-first: как приложение работает без связи

Если платформа доставки рассчитана на постоянную связь, сеть становится её слабым местом. А связь есть не всегда: ни у курьера на маршруте, ни на точке продаж в подвальном складе. Приложение, завязанное только на облако, перестаёт работать ровно тогда, когда идёт работа, — как только пропадает сигнал.

В offline-first-архитектуре логика обратная. Курьерское приложение продолжает работать без связи — принимает статусы, фиксирует подтверждение доставки — и синхронизируется автоматически, когда сигнал возвращается. В курьерском приложении Sizl это уже работает: курьер может снять фото-подтверждение доставки без интернета, приложение сохраняет его локально и синхронизирует само, как только связь восстановится. Причина, по которой это построили, была предельно конкретной — по словам самой команды, «в некоторых районах Чикаго слабый интернет». В основе лежит local-first-подход, построенный на React Native и RxDB. Сам термин «local-first» восходит к каноническому эссе исследовательской лаборатории Ink & Switch 2019 года, которое и назвало, и оформило эту категорию.

Разработка платформы доставки: как построить масштабируемую инфраструктуру для ресторанов и ритейла

Для ритейла та же устойчивость проявляется в магазине: приложение сборки заказов, которое продолжает давать сотрудникам собирать и подтверждать заказы во время перебоя связи, а потом сверяется, когда сеть возвращается, защищает операцию так же, как курьерское приложение.

Пять слоёв платформы и когда нужна кастомная разработка

Вот как все пять слоёв выглядят вместе:

Разработка платформы доставки: как построить масштабируемую инфраструктуру для ресторанов и ритейла

Главный вопрос — сколько из этого строить самому. Части бизнесов хватит готового решения. Если у вас один канал продаж, один-два агрегатора или маркетплейса и объём заказов не требует батчинга, достаточно готовой платформы оркестрации и стандартного назначения курьеров — кастомная инфраструктура здесь будет избыточной.

Кастомная разработка оправдана в трёх случаях. Первый — у вас три и больше агрегаторов или каналов одновременно, и нужен единый merchant-portal, чтобы управлять ими из одного места. Второй — заказов столько, что распределение на базе ML начинает реально окупаться. Третий — устойчивость к потере связи критична для операций, потому что курьеры работают в зонах слабого сигнала. В этих ситуациях типовой стек обходится дороже в костылях, чем кастомная разработка с нуля.

1