Разработка платформы доставки: как построить масштабируемую инфраструктуру для ресторанов и ритейла
- Почему платформа доставки ломается при росте нагрузки
- Маршрутизация и назначение курьеров — что на самом деле решает, кто повезёт заказ
- Отслеживание заказа в реальном времени: сокеты вместо поллинга
- Диспетчерская панель: как персонал управляет заказами
- Интеграция с агрегаторами: единое меню на всех площадках
- Offline-first: как приложение работает без связи
- Пять слоёв платформы и когда нужна кастомная разработка
- FAQ
Приложение доставки, которое обрабатывает 50 заказов в день, выглядит законченным. Курьеры получают назначения, клиент смотрит, как иконка движется по карте, заказы приезжают вовремя. Потом бизнес выходит на 500 заказов в день — и та же самая архитектура начинает рушиться: курьеров отправляют не по тому адресу, статус заказа отстаёт от реальности, а меню, которое вы выгрузили на три площадки, перестаёт совпадать от площадки к площадке — где-то висит цена, которую вы уже поменяли, где-то можно заказать блюдо, которого нет в наличии. Это не невезение. Эти ошибки были заложены в конструкцию ещё в первый день, потому что систему никто не проектировал под ту нагрузку, до которой она в итоге доросла.
Разработка платформы доставки — это построение архитектуры, в которую заложено масштабирование. В этой статье мы разобрали все пять архитектурных слоёв, от которых зависит, будет платформа доставки работать под нагрузкой или сломается: маршрутизация и назначение курьеров, live трекинг, диспетчерские инструменты, интеграция с агрегаторами и offline-first подход. Мы пройдём по каждому слою — сразу для ресторанов и для ритейла, — опираясь на публичный промышленный эталон (инженерный разбор алгоритмов Яндекс Доставки) и на наши собственные проекты.
Почему платформа доставки ломается при росте нагрузки
Слой приёма заказов — простая часть. Экран оформления, платёжный провайдер, каталог — это базовые задачи, и грамотный MVP закрывает их за пару недель. Настоящая сложность начинается после нажатия «Оформить заказ»: именно здесь решается, кто повезёт заказ, синхронизируются ли все участники по поводу того, где он сейчас, и удержится ли система целой, когда курьер въезжает в мёртвую зону или в магазине падает интернет.
Эти механизмы редко проектируют заранее, потому что на малых объёмах они работают без сбоев. Диспетчер окидывает взглядом десяток открытых заказов и раздаёт их вручную. Пока пользователей сотня, опрос сервера каждые несколько секунд ради обновления статуса выглядит мгновенным. Один агрегатор нетрудно синхронизировать вручную. На масштабе каждая из этих мелочей примерно одновременно превращается в полноценную инженерную задачу. Поэтому growth-stage-команды в доставке чаще всего получают все эти проблемы одним пакетом — и сразу.
Маршрутизация и назначение курьеров — что на самом деле решает, кто повезёт заказ
Назначение курьеров — это решающий узел платформы доставки: есть открытый заказ и пул курьеров (или точек сбора) — кто его берёт и в каком порядке? Ошибка на этом шаге бьёт в одну из двух сторон: курьер приезжает слишком рано и простаивает в ожидании готового заказа — или слишком поздно, и клиент получает остывшую еду. С ростом объёма добавляется батчинг: два-три заказа из одной кухни или соседних магазинов объединяют на одного курьера так, чтобы никто не выбился из срока доставки.
Первая ступень — ручное или полуручное распределение заказов по карте. Человек смотрит на карту, видит, какие заказы географически близки, группирует их и отдаёт тому, кто следующий в очереди. Ровно так сегодня устроена доставка курьерами у Sizl, сети dark kitchen из Чикаго: на экране группировки сборщик видит рядом готовые заказы и свободных курьеров, по карте объединяет близкие адреса в один рейс и вручную назначает его курьеру. Автоматизацию этой группировки мы планируем позже — пока ручной шаг сделан осознанно, потому что он позволяет команде видеть, где реально возникают узкие места, прежде чем зашивать вокруг них правила.

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

На что мы потратили 100 часов дизайна, чтобы в итоге спасти год разработки
Читать статьюОтслеживание заказа в реальном времени: сокеты вместо поллинга
Live трекинг обещает каждое приложение доставки. Реализуют его достойно куда реже. Самое частое упрощение — поллинг: клиент с фиксированным интервалом спрашивает у сервера «есть обновления?». На малом объёме это нормально. На масштабе — сажает батарею устройства, заваливает сервер запросами, которые в основном возвращают «ничего не изменилось», и всё равно отстаёт: обновление, которое вы видите, свежо ровно настолько, насколько свеж последний опрос.
Продакшн-приложения доставки вместо этого используют постоянное WebSocket-соединение и пушат изменения на клиент в момент, когда они происходят. Ably, инфраструктурный провайдер для realtime-систем, подробно разбирает техническое обоснование в своём сравнении long polling и WebSockets (май 2025): постоянное соединение снижает задержку и нагрузку на сервер по сравнению с периодическим опросом по мере роста числа подключённых пользователей. Это преимущество работает в обе стороны трекинга — и при пуше изменений статуса заказа клиенту, и при трансляции live-геопозиции курьера на карту.
Live-статус заказа и карту с курьером мы реализовали на Yapoki — высоконагруженном приложении доставки еды (20k+ скачиваний, 200+ заказов в день, 35% от общего объёма заказов бренда): клиент видит статус и следит за приготовлением в реальном времени, а движение курьера отображается на карте и обновляется автоматически. В курьерском приложении Sizl геопозиция курьера так же синхронизируется с картой и обновляется автоматически, пока он в пути. Во всех этих проектах мы намеренно берём проверенные геосервисы: Mapbox, Google Maps и OpenStreetMap.

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

Как уже сказано в разделе про назначение курьеров, сборка рейса здесь — ручная операция: сборщик группирует близкие заказы по карте, а автоматизация этого шага лежит в бэклоге.
В рознице всё то же самое: сотрудники магазина видят очередь заказов в панели, отмечают готовые и передают их курьеру.
Интеграция с агрегаторами: единое меню на всех площадках
Большинство ресторанов и многие ритейлеры продают не через один канал. Они держат собственное приложение и размещаются на агрегаторах — Wolt, Glovo, Яндекс Еда, Купер. Техническая ловушка в том, что у каждой площадки своя модель интеграции. Одни пушат события заказа вам через вебхуки; другие ждут, что вы будете опрашивать их сами. Обновления меню и каталога расходятся по разным площадкам с разной частотой. Без управления этим возникает рассинхрон: позиция, помеченная как отсутствующая в вашем POS, всё ещё доступна к заказу на одной площадке; новая цена обновилась на двух площадках, а на третьей осталась старая; и клиент заказывает то, что вы не можете отдать.
Здесь стоит заранее заложить в архитектуру две вещи.
Первая — как приходят заказы. Одни площадки присылают их через вебхуки, сразу в момент оформления: ваша сторона должна надёжно принять заказ, подтвердить его и при сбое повторить попытку. Другие работают по поллингу — новые заказы нужно самому запрашивать по расписанию, а значит, на вас ложится частота опроса и защита от дублей.
Вторая — частота обновлений. Наличие товаров и цены расходятся по площадкам с разной скоростью: отметка «нет в наличии» может сработать мгновенно на одной площадке и запоздать на другой.
Для самой физической доставки есть параллельный паттерн интеграции, который стоит знать. Вместо найма курьерского парка мерчант может обращаться к внешнему логистическому сервису по API. У Яндекс Доставки есть логистический API для бизнеса: запрос курьера одним API-вызовом, без собственного штата, — и это подходит не только ресторанам, но и аптекам, магазинам и ритейлу. Мы обычно закрываем этот слой одной платформой оркестрации доставки, а не подключаем каждого логистического партнёра по отдельности. Так с ростом числа каналов интеграция не разрастается.

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

Для ритейла та же устойчивость проявляется в магазине: приложение сборки заказов, которое продолжает давать сотрудникам собирать и подтверждать заказы во время перебоя связи, а потом сверяется, когда сеть возвращается, защищает операцию так же, как курьерское приложение.
Пять слоёв платформы и когда нужна кастомная разработка
Вот как все пять слоёв выглядят вместе:
| Слой | Что делает | Типовой инструмент / паттерн |
| Приём заказов | Принимает заказы из приложения, веба, агрегаторов | POS / каталог + оформление |
| Маршрутизация / назначение курьеров | Решает, кто и в каком порядке везёт; батчит близкие заказы | Ручное → по правилам → ML + оптимизация (VRP) |
| Live трекинг | Пушит статус заказа и геопозицию курьера вживую | WebSocket-соединение; Mapbox / Google Maps / OpenStreetMap |
| Диспетчерская / ops-панель | Даёт персоналу вести живую очередь заказов и передачи | Веб-панель мерчанта, синхронная с кухней/складом |
| Слой интеграции с агрегаторами | Держит меню/каталог и заказы в синхроне между каналами | Слой управления меню над POS; оркестрация доставки |
| Offline-first клиент | Держит курьерское/складское приложение живым без связи | Local-first (React Native + RxDB), автосинхронизация |
Кастомная разработка оправдана в трёх случаях. Первый — у вас три и больше агрегаторов или каналов одновременно, и нужен единый merchant-portal, чтобы управлять ими из одного места. Второй — заказов столько, что распределение на базе ML начинает реально окупаться. Третий — устойчивость к потере связи критична для операций, потому что курьеры работают в зонах слабого сигнала. В этих ситуациях типовой стек обходится дороже в костылях, чем кастомная разработка с нуля.

Архитектура FoodTech-приложения на React Native: как собрать стабильный продукт и не утонуть в деталях
Читать статьюFAQ
