
Иногда продуктовая фича живёт в приложении «для галочки». Пользователи вроде бы ею пользуются, команда её не развивает, а аналитики не могут толком оценить влияние на метрики. Так было с нашим старым механизмом поиска ближайших машин в каршеринге — «Радаром». Он просто пинговал координаты и сообщал, когда рядом появлялась машина. Никакой логики приоритизации, никаких фильтров, никакого резерва — сырая идея без развития.
В статье рассказываем, как мы заново осмыслили и пересобрали фичу:
— продакт Настя Голованова — о том, как мы нашли value, перезапустили механику и успели в сроки размещения наружной рекламы;
— разработчик Михаил Ефанов — про то, как превратить монолит в стабильную архитектуру.
Полезно будет всем, кто работает на стыке развитии продукта и инженерии: от старта фичи до релиза и плана развития.
Почему «Радар» нельзя было просто выключить
Старая реализация «Радара», казалось бы, ни на что не влияла, и её можно было просто убрать — никто не заметит. Но пользователи продолжали воспринимать его как важную часть сервиса: писали в поддержку и просили доработать. Это стало для нас сигналом — инструмент востребован даже в прежнем виде.
А ещё у нас копился внутренний запрос. Сотрудники, которые сами ездят на Ситидрайве, рассказывали:
«У офиса вечером машина очень быстро разбирают. Обновлять карту — утомительно. Нам бы радар поднять».
Кроме того, из-за сбоев в определении геопозиции искать машину вручную стало сложнее. Особенно в зонах с нестабильной связью: каждый раз открываешь карту — и снова надо искать свой дом или офис. С «Радаром» — поставил точку один раз, и сервис сам сообщит, когда рядом появится машина.
Так что спрос на инструмент был — и у пользователей, и внутри команды.
Как появилась идея переосмыслить старый «Радар»?
Из общения с пользователями стало ясно: бывают ситуации, когда человек готов уехать и даже подождать, но рядом просто нет доступных машин. Даже если аренда рядом вот-вот завершится, пользователь об этом не узнает — мы потеряли поездку, а каршеровод расстроился.
Проблема №1: Нет машин рядом.
Идея: Автоматический мониторинг ближайших машины в рамках времени, которое пользователь готов подождать.
Проблема №2: Гонка за бронированием в зонах высокого спроса. Особенно больно это ощущается в аэропортах. Пока один пользователь изучает карточку машины, другой уже её забронировал.
Идея: Добавить опцию резервирования автомобиля за пользователем сразу после того, как машина нашлась.
Проблема №3: Машина есть, но она не подходит. Бывает и так: машина рядом, но пользователь не едет. Причина — машина не та: кому-то нужен бустер, кому-то — только авто бизнес-класса.
Идея: Добавить фильтры по параметрам машины — от класса авто до опций вроде детского кресла, чтобы пользователь мог найти именно то, что ему нужно.
После формирования идей наступил этап оценки. Нам было важно посчитать, какой объём пользователей мы привлечём. Главная задача — оценить, сколько новых поездок мы реально сможем получить, исключая тех, кто и так готов бронировать авто и ехать.
Как это было посчитано:
Смотрим аналитику за последние 2 недели — отобрали все случаи, когда пользователь включил «Радар» (старую версию функции), но поездка так и не состоялась в течение ближайших 3 часов.
Для каждого такого случая проверили, появилась ли новая машина в радиусе 1 км в течение часа после запуска радара и оставалась ли она доступной хотя бы час.
Если такая машина появлялась, мы считали, что пользователь с 50% вероятностью совершил бы поездку, когда увидел бы машину и смог её забронировать.
За 2 недели было 33 тысячи случаев, когда после включения радара поездки не было. На основе этого мы сделали пессимистичную оценку экономического эффекта: улучшение логики радара могло бы дать значительный прирост GMV — только за счёт того, что мы «подсвечиваем» уже доступные машины тем, кто действительно готов ехать.
Итерации и гипотезы: как мы шаг за шагом создавали «Радар», который действительно работает
В процессе подготовки «Радара» мы тщательно изучили рынок, посмотрели какие решения уже существуют у других игроков. Анализ отзывов, в том числе в социальных сетях, помог выявить ключевые пожелания — например, необходимость строить маршрут не по прямой линии, а с учётом реальных пеших путей, обходящих реки и ж/д пути.

Несмотря на множество идей по доработке, мы не стали реализовывать весь функционал сразу. Выбрали стратегию поэтапного релиза, чтобы быстрее приносить ценность и проверять наши гипотезы на практике.
Так появились четыре этапа развития «Радара»:
Первый этап — обновление старой версии с двумя ключевыми улучшениями: построение изохроны, то есть области, границы которой рассчитываются с учётом реального времени пешей прогулки пользователя от центра выделенной области до границ этой области. А также настройка радиуса поиска не по расстоянию, а по времени пешей прогулки.
Второй этап — внедрение автобронирования. Теперь при включённой опции найденный автомобиль сразу резервируется — гарантируя, что вы не упустите шанс.
Третий этап — фильтры. Пользователи получили возможность выбирать класс авто, модели, а также дополнительные опции — детские кресла, бустеры, транспондеры.
Четвёртый этап — «период бронирования». Можно задать время старта и интервал поиска — «Радар» будет работать автономно.

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

Старая версия «Радара» осталась в монолите, поэтому наша стратегическая задача — перенести фичу на микросервисную архитектуру. Первым делом нужно было понять, какую нагрузку будет испытывать новый микросервис. Для этого мы проанализировали поведение старого проекта. В архитектуре монолита данные о текущих и завершённых «Радарах» хранились в PostgreSQL. Используя SQL-запросы и сопоставляя их с метриками шлюза (gateway), мы определили, что средняя нагрузка — около 0.5 запросов в секунду.
Понимая, что новая фича будет активно использоваться — мы заложили нагрузку в 2 RPS. Эта цифра стала отправной точкой для дальнейшего проектирования.
Проектирование API и ключевой функционал
Базовый набор функций, которые должен поддерживать API:
Создание радара;
Удаление радара;
Получение статуса радара;
Построение изохрон — зоны, достижимой за заданное время, для поиска доступных автомобилей.
Все эти операции уложились в привычный CRUD-подход. Интересный момент — построение изохроны мы решили не реализовывать самостоятельно, а подключиться к API 2GIS. Это позволило значительно снизить сложность и затраты. По нашим прогнозам, при полном использовании функционала пришлось бы делать около 16 миллионов запросов в месяц. Чтобы не перегружать систему и не увеличивать расходы, мы тщательно продумали стратегию кэширования ответов — да, кэширование не устарело и здесь оказалось жизненно важным.

Первая итерация: каналы и горутины
Первая идея реализации была вдохновлена возможностями Go: использовать каналы и горутины. Логика выглядела так — при создании радара открывается канал, в котором горутина выполняет поиск машин, а по результату отправляет уведомления. Казалось, что этот вариант идеально подходит для асинхронной обработки и параллельного поиска. Но на практике мы столкнулись с рядом сложностей:
Проблема масштабирования. При масштабировании сервиса на несколько подов запрос на получение статуса радара должен попадать в тот же под, где был создан канал. Это потребовало бы внедрения sticky sessions, что усложняло реализацию и требовало опыта, которого у команды на тот момент не было.
Перезапуск сервиса. При перезапуске сервиса состояние каналов теряется, и восстановление всех активных радаров стало бы нетривиальной задачей.

В итоге от этой идеи отказались, слишком сложно и ненадёжно в контексте нашего проекта.
Вторая итерация: Redis, Kafka и short polling
Следующая версия архитектуры выглядела так:
Хранение данных. Состояние радаров (создание, удаление, статус) сохраняется в Redis. Это позволило быстро обрабатывать CRUD-операции.
Генерация задач. Отдельный сервис (генератор задач) забирает все активные радары из Redis и формирует задачи, которые отправляются в Kafka.
Обработка задач. Следующий уровень сервисов обрабатывает задачи из Kafka, выполняя поиск машин по заданным параметрам и отправляя уведомления.
Флоу простыми словами:
API создаёт радар в Redis -> Генератор раз в N времени достаёт все активные радары и формирует на основе его данных задачи -> Перекидывает задачи в Kafka -> Под с основной логикой читает топик с задачами -> Проверяет освободившиеся машины в рамках изохроны -> Отправляет уведомление.

Для получения статуса радара мы выбрали механизм Short polling, а не Long polling и WebSocket по следующим причинам:
Простота реализации. Short polling не требует сложной инфраструктуры для поддержания постоянных соединений, как в случае с WebSocket, и минимизирует изменения на стороне сервера по сравнению с Long polling.
Предсказуемая нагрузка. Short polling позволяет клиентам периодически запрашивать статус, что легче прогнозировать и масштабировать, чем управление длительными соединениями в Long polling или WebSocket.
Совместимость с существующей инфраструктурой. Short polling не требует дополнительных настроек прокси или балансировщиков нагрузки, что упрощает развёртывание и снижает затраты на поддержку.
Хотя Short polling увеличивает количество запросов от клиента, он оказался наиболее подходящим компромиссом для нашего случая, учитывая ограничения по ресурсам и времени на разработку.
Проблемы масштабирования
При запуске нескольких подов, генератор в каждом из них создавал одинаковые задачи. В результате нагрузка на следующий уровень обработки дублировалась, что делало масштабирование неэффективным.
В качестве решения мы планируем разработать новый сервис, который назвали Taskkuler. Его задача — генерация уникальных задач, на основе ClickHouse (если интересно — подготовим об этом статью ?).
Это позволит централизовать процесс генерации задач и устранить дублирование, обеспечив масштабируемость системы. Сейчас Taskkuler находится на стадии планирования, и мы продолжаем прорабатывать детали его интеграции.
Ещё одной сложностью стала коммуникация через push-уведомления. APNS (Apple Push Notification Service) не гарантирует доставку и скорость уведомлений, что создавало риски для своевременного информирования пользователей. Чтобы минимизировать эту проблему, мы решили также использовать Short polling для передачи статуса поиска радара. Это позволило сделать систему более надёжной, хотя и увеличило нагрузку на клиентскую часть.

Каждый уважающий себя продакт доводит фичу до релиза
Есть расхожее мнение, что продакт — это человек с идеей, который «передаёт всё в разработку» и уходит думать дальше. В реальности — совсем не так. По крайней мере, у нас — в Ситидрайве продакт сопровождает фичу на всех этапах: от первой гипотезы до ретроспективы после релиза. А потом ещё следит, как она живёт в «реальном мире». Ну и делает фото билборда с релизом, чтобы мама гордилась ?.
Висим на каждом столбе
Первые релизы не «рвали чарты» по вовлечённости. Проблема была простая: пользователи просто не знали, что у нас что-то изменилось. К счастью, в Ситидрайве есть мощный тандем продукта и маркетинга. И это тот случай, когда всё сошлось: мы запустили удобную фичу, а маркетинг подхватил её на всех возможных поверхностях — от соцсетей до билбордов. Было приятно ловить наш релиз буквально по пути домой из офиса и одновременно наблюдать, как растут метрики использования.

Маркетинг не только круто подсветил проект, но и подбросил немного адреналина. У наружной рекламы есть точная дата выхода, и просто не существовало варианта не успеть с релизом к дедлайну. Конечно, был план Б, но к счастью, он не понадобился.
Как «Радар» влияет на бизнес-показатели
Запуск «Радара» — это не просто релиз удобной фичи, а сильный шаг в сторону продуктовой зрелости. За привычным интерфейсом — серьёзная бизнес-машина, которая уже через месяц показала результат. Поездки с использованием «Радара» принесли выручки в 3 раза больше, чем те, где им не пользовались.

Уроки проекта и выводы
Сейчас «Радар» поддерживает автобронирование и фильтрацию по ключевым параметрам автомобиля — от класса до дополнительных опций. Мы продолжаем развивать инструмент: у нас есть несколько гипотез по его дальнейшему улучшению, которые сейчас изучаем и тестируем.
Проект стал ценным опытом в решении классических задач микросервисной архитектуры: масштабировании, обеспечении надёжности уведомлений и выборе оптимальных технологий. В планах — запуск нового сервиса генерации задач, который обещает повысить эффективность системы, хотя и потребует внимательной интеграции.
Не претендуя на идеальное решение, команда открыта для обмена опытом и готова к обратной связи от сообщества ?
yaroslavp
Может не юзлес радар будете апдейтить, а реально нужные вещи, типо загрузки и определения местоположения не за 30 секунд, а почти мгновенно? Почему-то яндекс смог, как в навигаторе, так и в драйве. Вот это единственное, что прям раздражает