Пики в такси случаются не только из‑за роста заказов. Сервис “ломается” чаще из‑за каскада: диспетчеризация упирается в геопоиск, геопоиск тормозит из‑за карт, карты тормозят из‑за внешних поставщиков, а дальше растут таймауты, очереди и нагрузка на БД. В таких условиях цель деградации проста: сохранить минимально жизнеспособный поток заказов и оплат, а второстепенные функции ограничить или отключить.

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

Ниже разберём типовые сценарии деградации, что именно отключать при пике, как включать ограничения без “падения по умолчанию”, и какие ошибки повторяются чаще всего.

Сначала определите, что именно сохраняете: core flow и SLO

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

Практичный подход для такси:

  • Заказы должны создаваться и получать статус “в обработке” в разумный тайм-аут.
  • Мэтчинг/диспетчеризация должны находить водителя или возвращать ошибку предсказуемо, а не “вечно грузить”.
  • Платёж должен проходить по актуальному маршруту, без ручных операций и без “полуоплат”.
  • Минимальные уведомления должны уходить, чтобы пользователь и водитель понимали состояние заказа.

SLO задают не “как в идеале”, а “как достаточно”. Например, время ответа на создание заказа, частота успешных подтверждений, доля заказов, которые не переходят в финальные статусы. Важно ещё назначить SLI для ключевых точек: от API “create order” до “payment finalized”.

Когда вы фиксируете core flow и SLO, становится проще решать, что отключать: всё, что не влияет на этот поток, можно ограничивать или переносить на более позднее время.

Подготовка к отключениям: feature flags, лимиты и runbook до пика

Если отключать “вручную” в момент перегруза, вы почти гарантированно сделаете два вредных действия: включите слишком мало и слишком поздно, либо выключите то, что сейчас критично. Поэтому отключения должны быть подготовлены заранее.

Минимальная подготовка, которая реально помогает:

  • Переключатели через feature flags или конфиг-лейры (например, “отключить live tracking”, “снизить частоту ETA recalculation”, “выключить промо‑оценку при заказе”).
  • Rate limiting на входных шлюзах и на внутренних API (особенно на запросы к геосервисам и пересчёту маршрутов).
  • Circuit breaker и таймауты на внешние зависимости (геокодинг, карты, платежные провайдеры, SMS/email, чат).
  • Предопределённые стратегии деградации для каждого сценария перегруза (очереди, рост латентности БД, превышение лимитов карты, таймауты матчера).

Runbook должен быть написан под роли: SRE/инцидент-менеджер и инженеры команд. В нём указывают:

  • какие метрики включают аварийный режим (триггеры),
  • какие флаги и лимиты нужно менять,
  • в какой последовательности,
  • как понять, что достаточно, и как вернуться в штатный режим.

Один из частых провалов: команды знают, где “отключить” в коде, но не знают, как быстро безопасно сделать это через конфиг и как проверить эффект без повторного пика.

Триггеры пика: как распознать, что деградация уже нужна

Не стоит ждать полного отказа. С деградацией опираются на поведенческие признаки системы, а не только на число заказов.

Типовые триггеры, которые логично автоматизировать:

  • Резко растёт p95/p99 задержки на API создания заказа, матчера и диспетчера.
  • Внутренние очереди (Kafka/Rabbit/SQS/внутренние задачи) растут и не разгружаются.
  • В БД растёт доля запросов с блокировками/долгими транзакциями, либо увеличивается время выполнения агрегатов.
  • Геосервисы возвращают ошибки или растёт доля таймаутов при запросах к карте/геопоиску/маршрутизации.
  • У внешнего SMS/email/Push провайдера появляются ошибки, и ваша очередь уведомлений начинает “раздуваться”.

Ещё один полезный признак: несоответствие между успехами на одном шаге и провалами на следующем. Например, заказ создаётся, но подтверждение и переходы статусов “застревают”. Это обычно говорит о проблеме в матчинге, обработчиках статусов или в хранилищах.

Главное правило: деградацию включают при подтверждённом росте латентности и очередей, а не только при росте трафика. При правильных триггерах вы успеваете выключить “дорогие” вещи до того, как они начнут ухудшать всё вокруг.

Какие подсистемы обычно становятся “дорогими” в пике

Такси‑сервисы редко падают целиком сразу. Чаще деградируют отдельные компоненты, которые тянут ресурсы по цепочке.

Список подсистем, которые чаще всего становятся источником деградации:

  • Геозапросы: геокодинг, поиск точек, определение района, построение маршрута.
  • Пересчёт ETA/ETA‑интервалов: регулярные вычисления времени прибытия и статуса движения.
  • Live‑обновления: частые отправки координат, трекинг на карте, обновления маршрута и прогрессов.
  • Диспетчеризация/матчинг: сложные ранжирования, расчёт доступности водителя, обновления карты зон.
  • Уведомления: пуши, SMS, письма, webhooks для внешних систем.
  • Коммуникации: чат между водителем и пассажиром, медиа, вложения.
  • Доп. логика оформления: промо‑оценка, динамическое ценообразование “в моменте”, антифрод‑проверки в реальном времени.
  • Наблюдаемость: слишком детальные логи, синхронные трейсинги, выгрузки в сторонние системы в пике.

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

Что отключать при пике: матрица решений по подсистемам (практически)

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

1) Live tracking и частые обновления карты

Когда система перегружена, самая “широкополосная” часть — это частые обновления координат и отрисовка состояния. Их отключают или сильно разрежают.

Что обычно отключают:

  • Live‑трек пассажиру и водителю, или переводят его в режим “события вместо координат” (например, обновлять только при смене статуса).
  • Частые пересчёты отображаемого маршрута и прогресса на клиенте.
  • Обогащение трекинга: следы маршрута, детальные полигоны, анимации.

Что вместо отключения можно сделать:

  • Снизить частоту отправки координат (sampling).
  • Кэшировать последние валидные координаты и отдавть их клиенту по запросу, а не “стримить” постоянно.
  • На время отключить пересчёт детальных сегментов, но оставить события “прибыл/отменён/назначен”.

Типичная ошибка: отключить только “рисование” на клиентах, но оставить дорогие пересчёты на сервере. Вы получаете почти нулевой выигрыш по нагрузке.

2) Пересчёт ETA и вычисления “в реальном времени”

ETA часто считается дорогой. Даже если сама формула простая, проблемы возникают из‑за масштабов и зависимостей (трафик, маршрутизация, статистика ускорения/замедления).

Что отключают или переводят в упрощение:

  • Регулярный recalculation ETA с периодом меньше выбранного порога.
  • Пересчёт ETA при каждом событии координаты.
  • “Глубокие” модели, которые требуют внешних запросов к маршрутизатору/трафику.

Компромисс:

  • Оставить один пересчёт при важных событиях: назначение водителя, фиксация точки посадки, резкое изменение маршрута.
  • Если ETA критично для UX, можно оставить грубую оценку на основе скорости/расстояния без внешних вызовов.

3) Геопоиск и маршрутизация “по запросу пользователя”

При пике пользовательские действия (поиск точек, ввод адресов, изменение точек) могут резко увеличить число геозапросов. Эти шаги особенно уязвимы: они не только тяжелые, но ещё и имеют “внешние” зависимости.

Что обычно делают:

  • Включают жёсткое ограничение на геокодирование: кеширование результатов и дедупликация одинаковых запросов.
  • Временно отключают “поиск по мелким шагам” (например, автоподсказки на каждую букву), переводят ввод в режим подтверждения.
  • Для построения маршрута отключают пересчёт на каждое мелкое изменение и делают пересчёт только после подтверждения точек.

Если нужно выбирать:

  • Сохранить геопоиск для создания заказа (точки должны быть валидны).
  • Ограничить “вспомогательный” UX до статуса “работает базово”.

4) Дополнительные проверки перед созданием заказа

Антифрод, валидации, сложная проверка платёжеспособности или риск‑модель могут быть дорогими и иногда не критичными в момент пика.

Что чаще всего отключают при перегрузе:

  • Тяжёлые антифрод‑проверки, которые можно перенести в асинхронный контур после создания заказа.
  • Детальную валидацию промо/партнёров, если она не влияет на возможность назначения водителя.
  • “Глубокие” проверки доступности по тарифам, если есть fallback на базовый тариф.

Важно: платёжные проверки и маршруты оплаты не стоит ломать. Обычно безопаснее менять риск‑модель, а не способ провести оплату.

5) Динамическое ценообразование и промо-логика в моменте

Ценообразование может быть дорогим из‑за обращения к правилам, сегментам, внешним источникам и пересчётов на каждый шаг. В пике можно сделать упрощение.

Обычно отключают или ограничивают:

  • Пересчёт стоимости при каждом изменении параметров (оставить пересчёт только при подтверждении точек).
  • Сложные промо‑комбинации, если они требуют множества условий.
  • “Витринную” логику, которая нужна для маркетинга, но не для факта назначения и оплаты.

Компромисс:

  • Использовать базовый тариф и простые правила на время пика.
  • Возврат к полной модели — после стабилизации нагрузки.

6) Чат и обмен сообщениями

Коммуникации между пассажиром и водителем часто растут параллельно с заказами. Сам чат обычно не влияет на то, сможет ли диспетчер назначить водителя, но сильно влияет на нагрузку, особенно если есть медиа и вложения.

Что отключают:

  • Временно отключают вложения/медиа в чате.
  • Режим “read-only” для части сценариев (например, водитель может писать, а пассажир — пока только получать уведомления).
  • Снижают частоту отправки сообщений/подтверждений, если есть подтверждение доставки на сервере.

Практическое правило: чат можно “обрезать”, но не нужно останавливать жизненно важные уведомления о статусах заказа.

7) Уведомления: пуши, SMS, письма

Уведомления на пике часто превращаются в отдельную очередь. Это не только стоимость, но и риск: если очередь растёт, вы снова грузите БД и фоновые воркеры.

Что делает большинство команд:

  • При деградации переводят уведомления в режим “минимум”: только статусы заказа и ошибки критических шагов.
  • Откладывают маркетинговые рассылки и не критичные события.
  • Проводят rate limiting на пуши и SMS.

Нужно заранее определить “минимальный набор событий”. Например: назначен водитель, прибыл, отмена, успешная оплата, ошибка назначения. Всё остальное — на паузу.

8) Фоновые задачи и “дополнительные обработки после заказа”

Иногда весь сервис работает, но фоновые воркеры захлёбываются: пересчёт статистики, обновление витрины, аналитические джобы, выгрузки в DWH. Это не ломает core flow напрямую, но может убить хранилища и воркеры.

Что можно остановить:

  • Низкоприоритетные джобы, которые не влияют на статус заказа.
  • Обогащение аналитики “в моменте” и синхронные отправки в сторонние трейсинг/лог‑платформы.
  • Автоагрегации, если они “перетирают” ресурсы в момент пика.

Снова важное правило: фоновые задачи лучше ставить в очередь с пониженным приоритетом или откладывать, чем останавливать без контроля. После стабилизации вы должны быстро поднять их назад.

9) Наблюдаемость: логи и трейсинг

Наблюдаемость нужна, но не в виде “заливаем всё, пока горим”. На пике логи и трейсинги иногда становятся причиной деградации. Особенно если:

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

Что делают при перегрузе:

  • Сэмплируют трассировки и “раздувающие” логи.
  • Убирают подробные payload‑логи, оставляют метаданные.
  • Переходят на асинхронную отправку логов с буфером и ограничением.

Ошибка, которую встречают часто: сэмплируют только на клиенте или только для одного сервиса, а нагрузка остаётся в другом контуре (например, в воркерах и геосервисах).

Что не отключать: список критичных ограничений

Полезно заранее зафиксировать “красный список”: что нельзя отключать, иначе вы потеряете работоспособность core flow или создадите несогласованность статусов.

Обычно не отключают:

  • API создания заказа и базовые проверки валидности точек.
  • Матчинг/диспетчеризацию в минимальном режиме (пусть упрощённом).
  • Платёжные операции и фиксацию статусов оплаты.
  • Транзакционные обработчики статусов заказа: если водитель назначен, платёж должен быть корректно отражён.
  • Механизмы консистентности: идемпотентность обработчиков, защита от дублей.

Если хочется “выключить всё”, сервис может начать принимать заказы, но не завершать их. Это хуже, чем отказ: пользовательский поток возвращается снова и снова, создавая повторную нагрузку.

Вместо полного отключения обычно выбирают:

  • упрощение алгоритмов,
  • снижение частоты пересчётов,
  • временное ограничение не критичных функций.

Как оформить ограничения так, чтобы они реально помогали: механика деградации

Само “отключить X” мало. Нужна механика, которая даст предсказуемый эффект по нагрузке и не введёт логические баги.

Хорошая практика для деградации в такси:

  • Делайте ограничения детерминированными. Например, “ETA пересчитывать не чаще чем раз в N минут на заказ” или “live tracking отправлять только при смене статуса”.
  • Обеспечивайте идемпотентность. Когда вы отключаете/включаете обработчики, риски повторной отправки и дублей возрастают.
  • Разделяйте потоки. Например, создание заказа и “обогащение карточки” не должны разделять один и тот же воркер-пул.
  • Фиксируйте приоритеты очередей. Фоновые джобы должны быть ниже приоритета core flow.
  • Используйте backpressure. Если геосервис отвечает медленно, ограничивайте входящие запросы и возвращайте управляемые ответы (например, “повторите позже” на автоподсказки).

Набор “плохих” вариантов, которые часто не дают эффекта:

  • Отключить клиентские функции, но не серверные вычисления.
  • Уменьшить размер логов, но оставить синхронные внешние вызовы на пути к созданию заказа.
  • Отключить уведомления полностью, но оставить статусы без информирования пользователя и водителя, из-за чего растёт число отмен и повторных заказов.

Runbook: последовательность действий при перегрузе в такси

Ниже пример структуры runbook. Он не привязан к конкретным цифрам, но хорошо масштабируется на разные системы.

  • Подтвердите перегруз
  • Смотрите p95/p99 на ключевых API: create order, dispatch/matching, payment finalize.
  • Проверьте рост очередей и таймаутов в геосервисах и внешних уведомлениях.
  • Убедитесь, что причина системная, а не локальная (например, один регион или один пул инстансов).
  • Включите “уровень 1”: минимальная деградация без UX‑катастрофы
  • Отключите или снизьте live‑обновления (sampling или “события вместо координат”).
  • Уберите частый recalculation ETA, оставьте пересчёт на ключевых событиях.
  • Включите упрощённую геологику для UX: кешируйте, ограничьте автоподсказки.
  • Включите “уровень 2”: если очередь и таймауты не падают
  • Урежьте промо/динамическое ценообразование до базовых правил.
  • Ограничьте чат (отключить медиа, снизить подтверждения).
  • Переведите уведомления в минимальный набор статусов, остальное отложить.
  • Включите “уровень 3”: только если core flow под угрозой
  • Снижайте вычислительную сложность матчинг‑ранжирования до упрощённых критериев.
  • Переключайте риск‑проверки в асинхронный контур после создания заказа.
  • Сэмплируйте логи/трейсинг и отключайте низкоприоритетные фоновые джобы.
  • Наблюдайте эффект и возвращайтесь
  • Контролируйте: время создания заказа, долю успешных назначений, динамику очередей, долю таймаутов.
  • Возвращайте отключенные функции по одной, чтобы не вернуть нагрузку “всей кучей”.
  • После стабилизации запланируйте “вторую волну” — прогон отложенных задач, если это требуется.

Важно, чтобы в runbook были критерии “достаточно”. Например: когда latency стабилизируется и очереди перестают расти. Иначе команда возвращает флаги раньше времени.

Метрики, по которым вы поймёте, что деградация сработала

Деградация — это управляемая коррекция. Поэтому нужны метрики “до” и “после”, а ещё быстрые индикаторы, что вы не ухудшили core flow.

Минимальный набор метрик для контроля:

  • API success rate для создания заказа и назначения водителя.
  • Времена p50/p95/p99 по ключевым шагам.
  • Доля заказов, которые зависают между статусами (например, “ожидает назначения” слишком долго).
  • Размер очередей и скорость обработки (throughput) в фоновых воркерах.
  • Частота таймаутов и ошибок внешних зависимостей (карты, геопоиск, уведомления).
  • Ошибки консистентности: расхождения статусов заказа, повторные попытки платежа.

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

  • доля отмен после попытки назначения,
  • доля повторных заказов в короткий интервал,
  • доля ошибок “повторите позже” в геопоиске (это ожидаемо, но не должно расти бесконечно).

Типичная ошибка: оценивать деградацию только по нагрузке CPU. Можно “сбить” нагрузку, но ухудшить транзакционные пути, и сервис начнёт возвращать больше ошибок пользователю.

Частые ошибки при отключениях и как их избежать

Ошибка 1. Отключают не то место в цепочке

Логика “пользователь не видит трек” не означает, что исчезла нагрузка. Часто вычисления трекинга остаются на сервере, а нагрузка не падает.

Как избежать:

  • На каждом отключении привяжите эффект к конкретному узлу нагрузки (геосервис, матчер, воркеры, БД).
  • Проверяйте метрики: сколько запросов к геосервисам стало меньше, как изменилась задержка матчера.

Ошибка 2. Выключают уведомления слишком широко

Если отключить все нотификации, растёт число отмен и повторных действий. Пользователь и водитель теряют синхронизацию по статусам.

Как избежать:

  • Составьте минимальный набор обязательных событий и закрепите его в конфиге.
  • Остальное переводите в отложенную отправку или урезайте по приоритету.

Ошибка 3. Упрощение логики ломает финальные статусы

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

Как избежать:

  • Проверяйте зависимости: что требуется для payment finalize и закрытия заказа.
  • Делайте упрощение так, чтобы финализация работала на безопасных базовых правилах.

Ошибка 4. Нет обратного включения

После пика команды часто “забывают” вернуть флаги. Тогда сервис долго работает в деградированном UX‑режиме, а потом снова “упирается” в ту же нагрузку.

Как избежать:

  • Задайте в runbook таймеры и критерии возврата.
  • Фиксируйте ответственного за rollback и план пост‑инцидента.

Ошибка 5. Отключение начинается без идемпотентности

Если обработчики статусов не идемпотентны, при переключениях и ретраях возрастает риск дублей или пропусков.

Как избежать:

  • На ключевых обработчиках заказов и оплате держите идемпотентные ключи.
  • При деградации избегайте переключений, которые меняют порядок событий без контроля.

Минимальный набор “готовых” решений для такси на случай пика

Чтобы не каждый раз собирать деградацию заново, удобно иметь библиотеку флагов и заранее согласованные режимы.

Практичный список того, что стоит подготовить заранее:

  • Live tracking: sampling / режим событий / полное отключение (если не критично).
  • ETA recalculation: выключение частого пересчёта или переход на событийный пересчёт.
  • Геопоиск: включение кеша, ограничение автоподсказок, дедупликация запросов.
  • Маршрутизация: пересчёт только после подтверждения точек, отключение “мелких” триггеров.
  • Промо и динамика: упрощение правил и ограничение пересчёта при изменениях.
  • Уведомления: минимальный набор статусов и rate limiting.
  • Чат: отключение медиа и урезание подтверждений/частоты.
  • Фоновые задачи: приоритизация и отключение низкоприоритетных джобов.
  • Наблюдаемость: сэмплирование логов/трейсов и ограничение payload.

Каждый флаг лучше снабдить описанием:

  • что это отключает,
  • какой эффект по нагрузке ожидается,
  • какие SLO защищает,
  • что может ухудшиться у пользователя.

Так вы превращаете деградацию в управляемую систему, а не в набор “ручных экспериментов”.

Заключение: действуйте как инженер, а не как пожарный

Деградация сервиса такси при пике — это управляемый компромисс. Вы не “чините” систему отключениями, вы сохраняете core flow и удерживаете стабильность статусов и оплат, пока внешние и внутренние зависимости не возвращаются в норму.

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

Если у вас уже есть feature flags и контроль очередей, вы близки к готовности. Следующий шаг — документировать “что отключать при пике” по подсистемам такси и закрепить порядок действий, чтобы команда действовала одинаково и быстро, когда наступит очередной пик.