Готовьтесь к обрушению: как спроектировать приложение, чтобы «черная пятница» не превратилась в «черного лебедя».
В июле 2025 года россияне столкнулись со сбоями в работе системы быстрых платежей. Ошибки возникали при попытках авторизации в банковских приложениях, сами операции тормозили. Сбои в работе приложений не обязательно являются следствием хакерских атак или какого-либо другого внешнего воздействия (Роскомнадзор не зафиксировал следов вмешательства). Они могут возникать из-за ошибок в проектировании внутренней инфраструктуры приложений: одна из самых частых проблем – система не справляется со скачком трафика и рушится.
Степень цифровизации в России растет, популярность приложений по ряду направлений – тоже. До 2020 года «ВкусВилл» обрабатывал через приложение порядка 3 тыс. заказов в день. По состоянию на 2024 год этот объем составлял уже порядка 400 тыс. заказов в сутки.
Кратный рост нагрузки чреват рисками обрушения. С ним не справляются даже крупные участники рынка. В марте 2021 года была нарушена работа приложения банка Wells Fargo (входит в «большую четверку» банков США). Причина – кратный рост запросов: хронологически сбой совпал с датой выплат для поддержания потребительского спроса в период COVID-19. В 2023 году с аналогичными проблемами столкнулась The Hongkong and Shanghai Banking Corporation: один из крупнейших банковских холдингов мира оказался не готов к «черной пятнице». Любой сбой – это не только нагрузка на службу поддержки, это репутационные потери. В перспективе они оборачиваются потерей клиентской базы,конфликтами с контрагентами (в том числе, и в судах) и реальными убытками.
Каждый пользователь в такой ситуации – это потенциальная причина для критической нагрузки на инфраструктуру. Операция не выполнена, деньги не переведены, товар не заказан – юзер начинает повтор операции, количество запросов от одного человека кратно растет. Дальше возникает «эффект домино», система рушится.
У некоторых приложений, которые касаются социальной сферы жизни человека, есть своя «черная пятница». Она, например, гарантированно выпадает на утро каждого понедельника. В этот момент ряд ключевых сервисов оказывается под угрозой. У KODE был подобный проект: устойчивости достигли за счет метода горизонтального масштабирования. Добавили несколько реплик, нагрузка распределялась между ними. Как итог, добились устойчивости: получили меньше точек отказа, а за счет масштабирования нагрузка распределялась более равномерно. Устойчивость выстраивалась даже при пиках.

Причины, приводящие к негативному сценарию, выглядят примерно так:
Узкая архитектура критического пути (строится вокруг монолитных сервисов или синхронных вызовов)
Неоптимальные запросы к базе данных
Синхронные операции в высоконагруженном контуре (один медленный компонент начинает тянуть за собой все остальные)
Отсутствие изоляции между сервисами (всплеск запросов в одном домене рушит другие)
Ошибки в автоскейлинге (пиковая нагрузка растет быстрее, чем масштабируется инфраструктура)
Неуправляемая клиентская ретрай-логика (система не справляется с обработкой первичных запросов, но бомбардируется вторичными)
Отсутствие деградационных сценариев (оптимально спроектированная архитектура автоматически отключает неключевые функции при перегрузке).
Мощности с запасом
Главное отличие условной «черной пятницы» (момента, который создаст пиковую нагрузку на вашу инфраструктуру) от условного «черного лебедя» (изначально не прогнозируемое событие, которое приводит к непредсказуемым последствиям) в том, что ее появление можно просчитать. Скачки трафика хоть и не ведут себя линейно, но хронологически предсказуемы (даты распродаж, праздники, дни выплат). Мощности должны закладываться с запасом, чтобы инфраструктура не сыпалась при первом критическом скачке.
Хорошей практикой при разработке считается закладывать дополнительные мощности на уровне в 2-2,5, превышающие текущую пиковую нагрузку. Условно, если в данный момент она порядка 100 запросов в секунду, то необходимо при проектировании заклад��вать запас на 200-250 запросов, чтобы система могла справиться с ними без деградаций. В таком случае заранее просчитывает рост нагрузки, который может возникнуть при каких-либо маркетинговых активностях или интеграциях.
Базовый элемент устойчивости - механизмы балансировки трафика. Они, грубо говоря, нужны, чтобы один подвисший сервер не убил весь сервис. Балансировщик видит, какой из узлов живой, а кто тормозит. И просто не шлет туда новые запросы, повышая устойчивость системы к отказам и перераспределяя нагрузку.
Колебания трафика, как правило, неравномерны. Всплески в течение минуты могут в 5-10 раз превышать среднюю нагрузку. Балансировщик распределяет нагрузку таким образом, чтобы отдельные сервера не ловили эти пики напрямую. Если этого не сделать, система получит пиковый рост запросов на один узел и начнет рушиться.
Это один из вариантов, но не самый дешевый с точки зрения нагрузки. Есть и альтернативы.
Алгоритмов балансировки несколько:
Round Robin – базовый вариант. Запускаешь запросы кругу: первый сервер, второй, третий — и снова первый. Хорошо работает, если серверы одинаковые по мощности и нет долгих, «липких» запросов.
Weighted Round Robin – чуть более усложненная модель. Закладываешь все таким образом, чтобы более мощный сервер получал больше запросов, чем слабы (грубо говоря, учитываешь «вес»).
Least Connections – выбор в пользу сервера с минимальным числом активных соединений. Подходит для систем, где запросы занимают разное время.
Least Response Time – запрос идет туда, где минимальная задержка ответа. Чреват рисками: можно получить колебания нагрузки, если система слишком быстро реагирует на измерения.
Срок жизни – пара часов
Без оптимального механизма тестирования приложение не переживет пиковой нагрузки. Срок жизни в таком случае не превысит и пары часов.
Необходимо заранее проверить, как система ведет себя под реальной нагрузкой, в каких точках начнет «сыпаться». Здесь важно фиксировать: сколько времени сервер отвечает, сколько ошибок начинает выдавать, сколько запросов в секунду выдерживает один инстанс, в какой момент очереди (Redis, Celery, Kafka) начинают забиваться, и когда заканчиваются соединения к базе данных.
Пиковую нагрузку оптимально держать час-два. Тогда можно выстроить долгосрочный сценарий, как система будет вести себя в экстремальных условиях. Анализ на коротком всплеске трафика такого понимания не дает.
Чтобы проверить, насколько система реально устойчива к экстремальным условиям, используют методику chaos engineering, когда разработчики сознательно устраивают коллапс для собственного продукта: сервисы отключаются, создаются искусственные задержки, базы данных летят вниз.
Разработчики моделируют хаос
Обычные тесты проверяют «все ли идет по плану», хаос — «что случится, если прямо сейчас половина серверов умрет?»
Контролируемый хаос, который модулирует тестировщик, позволяет находить слабые места в архитектуре при форс-мажоре: узкие места, неоптимальные запросы, отсутствие кэширования, плохо выстроенная балансировка трафика. Это позволяет отработать пессимистический сценарий: что случится, если один элемент замедлится или пойдет в отказ, где нет резервов.
При chaos engineering разработчик намеренно создает перегрузку: направить такое количество запросов, сколько система не может просчитать. Это позволяет вычислить, где начинается торможение.
- Правильно будет проверить систему на зависимость: один из сервисов выключается, если все остальные падают значит архитектура неустойчива.
- Компоненты сознательно замедляются. Если приложение виснет – уязвимость вычислена.
- Моделируется ситуация, когда кончаются соединения к базе данных, память у сервиса или место на диске. В реальности, системы именно так и рушатся.
- Идет симуляция сетевых проблем: задержки, нестабильный интернет, потери пакетов.
- Логика, в рамках этой системы, тоже ломается. Для системы формируются странные запросы, некорректные события, дубликаты. Если приложение не включает фильтрацию и не отбрасывает спам, то все падает.
Альтернативы есть
Есть несколько методик, способных обеспечить устойчивость приложения в момент пиковых нагрузок
Модель шардирования: большой объем данных делится на части. Как следствие, система работает быстрее и может справиться с большими нагрузками. Вместо одной огромной базы у тебя присутствуют несколько – те самые шарды. Каждый хранит свою часть данных. Приложение обращается к нужному шарду по ключу. Это спасает от излишней нагрузки на базу данных.
Метод репликации. У базы данных несколько копий. Если основной узел падает, то все переключается на реплику. Если с основной базой что-то пошло не так, то можно перестроить узел из реплики.
Горизонтальное и вертикальное масштабирование. Формируешь новые сервисы и инстансы, а не раздуваешь один до бесконечности. Или увеличиваешь ресурсы одного узла: CPU, RAM, SSD. Но при этом сценарии ресурс ограничен.
Защитный механизм Retry + Backoff. Пригодится в тех случаях, когда запрос «ломается» не из-за ошибки в коде, а из-за временных проблем: сеть моргнула, сервис завис на секунду, база дала таймаут.
Деградационные сценарии. Сервис падает, но приложение остается живым, хоть и показывает только усредненный вариант: вместо полной персонализации – дефолтный контент.

Устоять на пике
Пиковый трафик может носить цикличный характер. К примеру, всплеск гарантированно приходится на начало осени каждого года, если мы говорим о социальных или образовательных проектах. На сервис идет дополнительная нагрузка, все эти моменты необходимо просчитать заранее.
У нас был проект, где пиковая нагрузка гарантированно возникала в определенный день календаря (дату прекрасно знали). Чтобы приложение не рухнуло, проводилось нагрузочное тестирование. Из оптимальных и универсальных решений –был установлен запрет на релизы к часу X (две недели до и после). Если проект был построен на совокупности сервисов, и все они релизятся в один момент, то вычислить, какой из них упал, будет достаточно затруднительно.
Архитектуру для данного приложения проектировали на наборе автономных сервисов: они относительно изолированы друг от друга, каждый - отдельная часть системы. Изолированность сервисов – гарантия, что в случае превышения нагрузки, все не посыпется одномоментно.
На уровне управления инфраструктурой был задействован Kubernetes. Он удобен тем, что автоматически распределяет нагрузку между «контейнерами», поднимает тех, кто «упал», мониторит, чтобы у каждого был свой объем трафика.
Плюс, для каждого сервиса снова включали горизонтальное масштабирование. Для каждого сервиса, в который включена база данных, прописывали реплику. В итоге получили дополнительные возможности по балансировке: все операции, связанные с записью данных, направляли на оригинал, все, что связано с чтением – на реплику.
В какой-то момент мощности все равно стали подходить к пределу. Тогда были запущены оптимизационные сценарии, чтобы снизить глубину запросов. Для этого ввели дополнительные параметры (у пользователя появилась возможность просмотреть данные за более короткий период, а не за всю историю).
Для оптимизации наращивали объем кэширования данных в клиентской части или промежуточных системах, чтобы лишний раз не беспокоить сервер.
Пик – это данность
В условиях современного рынка пиковые нагрузки – это не нонсенс, а данность. У любого сервиса в какой-то момент возникает своя условная «черная пятница»: трафик растет, но все ведет не к увеличению монетизации, а глобальному сбою и репутационным потерям. Система, которая не прошла стресс-тест, обязательно рухнет. И именно в тот момент, когда этого ждут меньше всего.
Без нагрузочного и хаос-тестирования любая система «умрет» при первой же пиковой нагрузке. Если не учесть при проектировании дополнительные мощности, то приложение будет жить только в тепличных условиях. Как только трафик вырастает чуть выше обычного – готовьтесь к обрушению.
