Асинхронная активация подарочных карт: продолжение истории
После автоматизации склада активность на сайте выросла. В пиковые дни количество активаций доходило до десятков тысяч в сутки. Синхронная активация начала давать сбои: задержки, дублирование запросов, ошибки в данных. Мы перевели активацию на асинхронную обработку через RabbitMQ и Laravel Jobs, увеличили количество воркеров и подключили WebSockets для мгновенного обновления баланса. Нагрузка снизилась, дубли исчезли, пользователь видит результат сразу.
Напомним: с чего всё началось
В прошлой статье мы рассказывали, как автоматизировали склад подарочных карт и убрали ручной труд: заменили Excel на админ-панель, внедрили активацию без менеджера, отчёты и API для 1С.
Тогда казалось, что задача решена. Но у этой истории оказалось продолжение, и оно про то, что происходит, когда автоматизация начинает работать слишком хорошо.
Рост активности: проблема, которую мы не планировали
После запуска автоматизации активность на сайте начала расти. Клиенты массово пользовались активацией подарочных карт — это было ожидаемо и приятно.
Но в пиковые моменты — праздничные дни — количество активаций в сутки доходило до нескольких десятков тысяч.
И тут проявилась обратная сторона успеха.
Как работала активация: синхронный подход
Изначально активация была синхронной:
-
Человек вводит код карты.
-
Отправляется запрос на бэкенд.
-
Выполняется бизнес-логика активации, включая запросы в СУБД.
-
Клиенту возвращается ответ.
Для небольших объёмов это работало отлично. Но при большом количестве одновременных запросов начались проблемы:
-
Задержки — из-за ограничений мощности и невозможности параллельной обработки синхронных операций.
-
Дублирование запросов — в пиках от клиента поступали два идентичных запроса, и оба проходили. Это вызывало проблему с данными и приводило к ошибкам.
Самое неприятное в дублях: пользователь мог получить двойное начисление, а система — рассогласованные данные. Это уже не просто «медленно», это инцидент.
Решение: асинхронная обработка через RabbitMQ и Laravel Jobs
Мы решили кардинально поменять подход к активации. Все процессы, по которым были просадки, вынесли на асинхронную обработку.
Что применили:
-
RabbitMQ — брокер очередей для управления задачами.
-
Laravel Jobs — стандартный механизм очередей фреймворка.
Как изменился пользовательский сценарий:
-
Пользователь вводит код карты.
-
Проходит валидация (проверка формата, срока действия и т.д.).
-
Если валидация пройдена — выводится сообщение: «Ваша активация принята, ожидайте поступления средств».
-
Задача уходит в очередь, где обрабатывается асинхронно.
Это сразу сняло нагрузку с синхронного пути и убрало проблему с дублирующимися запросами.
Новый вызов: одного потока не хватило
Асинхронная обработка запускалась в один поток. Этого хватало для стабильности, но не для скорости.
Пользователь ждал поступления средств дольше, чем хотелось. Для «мгновенной» активации одного воркера было недостаточно.
Что мы сделали:
-
Увеличили количество потоков для обработки активаций.
-
Проблема с задержкой ушла — активации стали обрабатываться быстро даже в пиковые дни.
Новая проблема: пользователь не видит баланс «здесь и сейчас»
Асинхронность решила проблемы с нагрузкой и дублями, но создала новую проблему пользовательского опыта.
Раньше: пользователь активировал карту и сразу видел обновлённый баланс.
Теперь: пользователь видит сообщение «ожидайте поступления средств» — и не понимает, когда именно деньги появятся на счёте.
Это расстраивало пользователей. Ожидание без обратной связи всегда воспринимается хуже, чем мгновенный результат — даже если фактически обработка занимает секунды.
Решение: WebSockets для мгновенного обновления баланса
Мы подключили WebSockets — технологию, которая позволяет серверу отправлять данные клиенту в реальном времени, без необходимости обновлять страницу.
Как это работает:
-
Пользователь отправляет запрос на активацию.
-
Задача уходит в очередь.
-
Как только воркер обрабатывает активацию — сервер транслирует событие через WebSocket.
-
Баланс в шапке сайта обновляется автоматически — без перезагрузки страницы.
Пользователь видит: «Активация принята» → через секунду баланс меняется. Ощущение мгновенности вернулось, хотя технически процесс остался асинхронным.
Результат: что изменилось
Главный итог: мы уменьшили нагрузку на сайт, убрали задержку активации для сотрудников, решили ошибку с дублирующимися запросами — и при этом сохранили для пользователя ощущение мгновенного результата.
Стек
-
Backend: Laravel (PHP)
-
Очереди: RabbitMQ + Laravel Jobs
-
Real-time: WebSockets
-
База данных: MySQL
Что мы вынесли из этой истории
1. Успех автоматизации — это не финиш, а новый старт
Рост активности — это хорошо. Но он открывает проблемы, которых не было при малых объёмах. К этому нужно быть готовым.
2. Синхронность — враг пиковых нагрузок
Всё, что может быть асинхронным, должно быть асинхронным. Это снимает нагрузку и убирает целый класс ошибок (например, дублирование запросов).
3. Асинхронность без обратной связи — плохой UX
Пользователю не важно, как устроена система внутри. Ему важно видеть результат. WebSockets — простой способ вернуть ощущение мгновенности.
4. Масштабирование — это итеративный процесс
Сначала один воркер, потом несколько. Сначала синхронно, потом асинхронно. Сначала без real-time, потом с WebSockets. Не нужно строить идеальную систему сразу — нужно решать проблемы по мере их появления.
Вместо заключения
Эта история — про то, что хорошая автоматизация всегда ведёт к росту, а рост — к новым вызовам. Мы прошли путь от синхронной активации к асинхронной, от одного воркера к нескольким, от «ожидайте» к мгновенному обновлению баланса.
И это, скорее всего, не конец. Но именно так и работает сопровождение продукта: не «сделали и забыли», а развиваем и решаем проблемы по мере роста.