Системы оплаты проезда и билетов: как мы проектируем решения под нагрузку и рост

Почему транспортные платежи — отдельный класс задач
Когда заказчик говорит «нам нужна онлайн-оплата проезда», за этой фразой скрывается не интернет-магазин с корзиной, а инфраструктура реального времени. Пассажир валидирует карту на турникете или у кондуктора, и решение «пускать или нет» система обязана принять за доли секунды — независимо от того, есть ли в этот момент связь с банком, перегружен ли сервер и сколько таких же пассажиров прикладывают карту в эту же секунду в других точках города.
Это меняет всё. Обычный e-commerce может позволить себе показать спиннер на две секунды и баннер «попробуйте позже». В транспорте «попробуйте позже» означает очередь на входе в метро, заблокированный турникет и недовольство тысяч людей одновременно. Поэтому транспортные платёжные системы проектируются вокруг трёх свойств: предсказуемая задержка, устойчивость к пиковым нагрузкам и корректность учёта денег даже при сбоях.
Мы в OneDev подходим к таким проектам как к финтех-инфраструктуре с жёсткими SLA, а не как к веб-приложению с платёжной формой. Ниже — как мы рассуждаем об архитектуре, какие решения принимаем и какие ошибки чаще всего видим у систем, доставшихся в наследство.
Нагрузка в транспорте неравномерна — и это главное
Главная особенность транспортных платежей — резкая неравномерность трафика. Утренний и вечерний час пик дают всплеск в десятки раз выше среднесуточного уровня. На крупной станции метро в течение нескольких минут проходят тысячи валидаций, и каждая из них — отдельная транзакция, которую нужно проверить, списать и записать.
Проектировать систему под средний показатель — классическая и дорогая ошибка. Считать нужно пиковую секундную нагрузку (TPS, транзакций в секунду) на самой загруженной точке в самый загруженный момент, а затем закладывать запас сверху. Если средний поток — 50 транзакций в секунду, а пик на крупном узле даёт 1500, проектировать надо под 2000–2500, иначе система ляжет именно тогда, когда она нужнее всего.
- Пиковый TPS на узел, а не усреднённый по сети за сутки.
- Сезонность и события: праздники, спортивные матчи, погодные аномалии меняют поведение пассажиров.
- Холодный старт утром: одновременное «пробуждение» тысяч валидаторов и их синхронизация с центром.
- Деградация связи: 3G/4G в тоннелях и на удалённых маршрутах нестабильны, а оплата должна работать.
Офлайн-режим: то, что отличает транспорт от любого магазина
Связь в транспорте пропадает регулярно: метро под землёй, пригородные автобусы на трассе, паромы. Система, которая отказывает в проезде при потере интернета, нежизнеспособна. Поэтому критичный архитектурный принцип — валидатор должен уметь принять решение локально.
На практике это означает, что валидатор хранит локальные списки (белые и чёрные), правила тарификации и буфер транзакций. Если связи нет, устройство принимает решение по локальным данным, записывает транзакцию в очередь и синхронизирует её с центром, как только канал восстановится. Центральная система при этом обязана корректно обработать «задержанные» транзакции, пришедшие пачкой через минуты или часы.
Деньги нельзя терять и нельзя списывать дважды
Финансовая корректность — то, что прощают меньше всего. Пассажир не должен быть списан дважды за одну поездку, а перевозчик не должен недосчитаться выручки из-за «потерянной» транзакции. При распределённой системе с офлайн-буферами и повторными отправками это нетривиально.
Базовый инструмент здесь — идемпотентность. Каждая транзакция получает уникальный идентификатор на устройстве в момент создания, и сервер при повторном получении того же идентификатора не проводит операцию заново, а возвращает прежний результат. Это защищает от двойных списаний при ретраях после обрыва связи.
Поверх этого обязательна регулярная автоматическая сверка (reconciliation): данные валидаторов, центральной системы и банка/процессинга должны сходиться. Любое расхождение — это инцидент, который нужно ловить автоматически, а не обнаруживать в конце месяца при сведении отчётности.
Архитектура, которая выдерживает рост
Систему оплаты проезда нельзя строить как монолит, который при росте сети просто «ставят на сервер помощнее». Вертикальное масштабирование упирается в потолок, и именно в час пик. Мы проектируем такие решения вокруг нескольких принципов.
- Горизонтальное масштабирование без состояния: сервисы приёма транзакций не хранят сессионное состояние в памяти, что позволяет добавлять инстансы под нагрузку.
- Очереди и буферизация: входящие транзакции принимаются быстро и складываются в очередь (например, брокер сообщений), а тяжёлая обработка идёт асинхронно. Это отделяет пиковый приём от скорости обработки.
- Разделение горячего и холодного пути: валидация и решение «пускать» — отдельный быстрый контур; аналитика, отчётность и биллинг — отдельный, не мешающий первому.
- Кэширование правил тарификации: тарифы и лимиты меняются редко, поэтому они кэшируются и не дёргают базу на каждую транзакцию.
- Изоляция отказов: падение модуля отчётности не должно ронять приём оплаты.
Безопасность и соответствие требованиям
Платёжные данные — зона повышенной ответственности. Если система работает с банковскими картами напрямую, в игру вступают требования PCI DSS, и грамотный путь — не хранить данные карт у себя, а использовать токенизацию и процессинг на стороне сертифицированного провайдера. В контексте Узбекистана это также интеграция с локальными платёжными системами и банковской инфраструктурой, локализация хранения данных и работа с местными процессингами.
Отдельный пласт — защита самих валидаторов от подделки баланса и клонирования карт, шифрование каналов между устройствами и центром, аудит всех операций. Транспортная карта — это, по сути, носитель денег, и относиться к ней нужно соответственно.
Типичные ошибки унаследованных систем
Когда нас зовут переделать существующую систему, мы чаще всего встречаем один и тот же набор проблем. Понимание этих граблей помогает не наступить на них в новом проекте.
- Нет офлайн-режима — система парализуется при потере связи именно там, где связь нестабильна.
- Синхронная обработка «в лоб» — каждая транзакция ждёт банк, и в пик всё встаёт в очередь.
- Отсутствие идемпотентности и сверки — учёт «плывёт», расхождения копятся незаметно.
- Жёстко зашитые тарифы — изменение цены проезда требует релиза и простоя вместо смены конфигурации.
- Нет наблюдаемости — нет метрик TPS, задержек и доли ошибок, поэтому деградацию замечают по жалобам пассажиров, а не по дашбордам.
Последний пункт мы считаем обязательным с первого дня: мониторинг задержек, очередей, доли отклонённых операций и расхождений сверки — это не «улучшение на потом», а часть несущей конструкции. Без него вы управляете системой вслепую.
Вывод
Системы оплаты проезда — это финтех-инфраструктура реального времени, где цена архитектурной ошибки измеряется не багами, а очередями, потерянными деньгами и репутацией. Надёжное решение строится вокруг пиковых нагрузок, офлайн-устойчивости валидаторов, идемпотентного учёта с автоматической сверкой и архитектуры, которая масштабируется по частям вместе с ростом сети. Если вы планируете запуск или модернизацию транспортной платёжной системы в Узбекистане — расскажите нам о маршрутах, ожидаемом пассажиропотоке и текущей инфраструктуре, и команда OneDev поможет спроектировать решение, которое выдержит и сегодняшнюю нагрузку, и завтрашний рост.
Сколько транзакций в секунду должна выдерживать транспортная платёжная система?
Что произойдёт, если на валидаторе пропадёт связь?
Как исключить двойное списание за одну поездку?
Нужно ли нам сразу строить микросервисы?
Хранит ли система данные банковских карт?
Можно ли модернизировать существующую систему без остановки работы?
Нужна похожая система или хотите обсудить проект?
Опишите задачу — предложим архитектуру, технический подход и план работ. Часто для старта достаточно короткого звонка.
Обсудить проект