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

Почему счёт растёт раньше, чем трафик
Счета за облако часто растут задолго до того, как вырастает поток клиентов. Обычно причина проста: команда быстрее добавляет новые части, чем убирает старые.
Небольшая команда под давлением выбирает самый быстрый способ решить проблему. Добавляет очередь для фоновых задач, вторую реплику базы данных «на всякий случай», ещё один инструмент для логов, потому что первый кажется ограниченным, и отдельный сервис для поиска или авторизации. В моменте каждое решение выглядит разумным. А потом мало кто возвращается и спрашивает, нужен ли старый элемент вообще.
Так и начинается архитектурное лишнее. Вы не видите одну лишнюю строку в счёте. Вы получаете цепочку затрат вокруг каждого нового сервиса: вычисления, хранилище, резервные копии, логи, мониторинг, шаги деплоя и время поддержки, когда что-то ломается.
Эту стоимость поддержки легко не заметить. Сервис, который стоит 80 долларов в месяц, всё равно может вызывать алерты, запуск резервного копирования, странные баги и часы работы инженеров. В счёте видна одна сумма. Команда платит гораздо больше.
Дублирование делает проблему хуже. Команды часто платят дважды за одну и ту же задачу в двух местах. Одна система отправляет события в аналитический инструмент, хранилище и платформу логов, хотя решения принимает только одно из них. Другая команда запускает отдельные воркеры и очереди для задач, с которыми могла бы справиться одна job system.
У растущей SaaS-команды может получиться так, что когда-то простое приложение делят на пять небольших сервисов. Трафик удваивается, а счёт утраивается. Это происходит потому, что каждый сервис приносит с собой собственный экземпляр, секреты, логи, проверки здоровья, резервные копии и процесс деплоя. Продукт не стал в три раза полезнее. Он просто стал тяжелее.
Скидки у облачных провайдеров могут помочь, но они редко решают настоящую проблему. Если в дизайне есть дублирующие сервисы, простаивающие реплики и лишние очереди, более низкий тариф лишь удешевляет лишнее. Он его не убирает.
Поэтому архитектурные решения часто важнее закупок. Если один запрос клиента проходит через шесть платных сервисов, прежде чем завершится, расходы будут быстро расти, даже если трафик пока выглядит умеренным.
Где лишнее прячется на виду
Большая часть лишних облачных расходов выглядит не драматично. Она выглядит разумно, даже аккуратно. Команда добавляет ещё один сервис, ещё одну реплику, ещё одну очередь, а через шесть месяцев уже никто не помнит, зачем эта часть вообще осталась.
Частый пример — дублирующая фоновая работа. Один сервис обрабатывает письма, отчёты или файлы. Потом кто-то в спешке добавляет второго воркера, и оба остаются включёнными даже после того, как спешка закончилась. Задачи всё равно выполняются, поэтому никто не жалуется. Но теперь два сервиса следят за одной и той же нагрузкой, пишут одинаковые события в логи и сжигают деньги весь день.
С репликами базы данных происходит то же самое. Read replica оправданы, когда трафик большой или отчёты сильно нагружают основную базу. Но многие команды держат их и после того, как пик давно прошёл. Если реплика большую часть дней почти не использует CPU и обслуживает совсем мало реального трафика, это просто дорогая привычка.
Очереди тоже переживают проблему, для которой их когда-то создали. Команда добавляет одну, когда синхронные запросы начинают тормозить во время запуска. Потом код улучшается, трафик стабилизируется, а очередь остаётся. Теперь приложение платит за очередь, за парк воркеров за ней и за дополнительный мониторинг вокруг всего этого.
Перекрытие инструментов — ещё одна тихая утечка. Команды платят за отдельные инструменты поиска, кеша и расписания, хотя один или два компонента могли бы справляться достаточно хорошо. Отдельный cron-сервис, message broker с отложенными задачами и планировщики на уровне приложения в итоге делают примерно одно и то же. То же самое касается поисковых продуктов, которые индексируют крошечный набор данных, и кешей, где в основном лежит то, что база данных может вернуть за миллисекунды.
Неproduction-окружения часто оказываются самой игнорируемой строкой расходов. Staging, QA, demo и preview-сборки начинают как временные помощники. Потом они работают 24 часа в сутки, 7 дней в неделю, хотя ночью и в выходные ими никто не пользуется.
Обычно о лишнем говорят несколько признаков. Две системы обрабатывают одну и ту же задачу, но никто не может объяснить, зачем обе до сих пор нужны. Реплика, очередь или кеш неделями показывают очень низкую загрузку. Старое временное решение всё ещё работает после того, как авария или всплеск трафика, ради которых его включили, уже давно закончились. Тестовые и staging-системы остаются включёнными, даже когда команда офлайн.
Если вы хотите сократить расходы на облако, начните с этого, а не с просьбы о скидке. Закупки могут сэкономить 5%. Удаление одного забытого сервиса может дать больше, и эта экономия будет идти каждый месяц.
Как разбирать стек шаг за шагом
Начните с одного реального действия клиента, а не с общей схемы системы. Выберите что-то привычное, например «пользователь входит в систему», «клиент загружает файл» или «команда экспортирует отчёт». Один путь говорит больше, чем стена из коробок, потому что показывает, что именно просыпается, когда деньги уходят с вашего счёта.
Нарисуйте этот путь от первого клика до финального ответа. Включите каждый API, воркер, очередь, чтение базы, hit в кеш, фоновую задачу и реплику, которые в нём участвуют. Если одно простое действие затрагивает восемь сервисов, две очереди и три хранилища данных, вы, скорее всего, уже нашли лишнее.
Для такого разбора достаточно обычной таблицы. Для каждой строки укажите один компонент и четыре вещи: что он делает, как часто запускается, сколько стоит и что сломается, если его выключить. Последняя колонка важнее, чем многие думают. Команды месяцами держат лишние части, потому что никто не знает, нужны ли они ещё.
Затем возьмите данные за 30 дней по каждому элементу этого пути. Посмотрите на использование, уровень ошибок и задержку. Одна только стоимость может ввести в заблуждение. Очередь может казаться дешёвой, но если она почти не несёт трафика и добавляет задержку, она всё равно ухудшает систему. Реплика может казаться надёжной, но если она большую часть дней почти простаивает, вы платите за спокойствие, а не за необходимость.
Картина обычно становится очевидной, как только вы смотрите внимательно: сервисы, которые просыпаются лишь на несколько запросов, реплики почти без read-трафика, очереди с крошечной глубиной и без всплесков, базы, которые в основном зеркалят данные откуда-то ещё, и воркеры, работающие весь день ради задач, которые появляются два раза в час.
Убирайте по одному элементу за раз. Объедините один сервис с другим. Удалите одну очередь. Уменьшите одну реплику. Потом несколько дней наблюдайте за уровнем ошибок, задержкой и обращениями в поддержку. Маленькие изменения скучны, и это хорошо. Скучные изменения редко кладут production.
Многие SaaS-команды обнаруживают, что больше всего в счёте дают старые «временные» части. Команда может держать отдельный сервис воркеров, очередь сообщений и read replica ради отчёта, которым пользуются пять клиентов в неделю. Возврат этого потока в основное приложение может сэкономить больше, чем любая скидка от вендора.
Разбирайте стек в том порядке, в котором им пользуются клиенты. Пройдите один путь, измерьте каждый шаг и уберите то, что почти ничего не делает.
Что оставить, прежде чем что-то убирать
Сокращение расходов идёт не так, когда команды удаляют части, которые тихо защищают выручку. Оставляйте то, что каждый день отрабатывает своё место: защищает доступность, принимает реальную нагрузку или позволяет командам выпускать изменения, не блокируя друг друга.
Начните с реплик. Если платные пользователи ожидают, что приложение будет работать даже при сбое одного узла, оставьте столько реплик, сколько нужно для такого отказа. Одна дополнительная реплика приложения за балансировщиком может быть недорогой страховкой. Пять реплик в нескольких зонах для продукта с лёгким и предсказуемым трафиком — обычно нет.
Используйте тот же подход для баз данных и кешей. Оставьте ту схему failover, которая действительно нужна для тех целей восстановления, которые вы обещали. Не держите более крупную конфигурацию только потому, что раньше во время запуска она казалась безопаснее.
С очередями тот же честный подход. Очередь полезна, когда трафик приходит рывками и остальной системе нужно время, чтобы догнать нагрузку. Обработка изображений, импорты, повторные отправки вебхуков и письма часто подходят под такой сценарий. Очередь, которая весь день двигает маленький поток задач без реальных всплесков, может просто добавлять ещё один объект для мониторинга.
Отдельные сервисы стоит сохранять, когда команды выпускают их по разным графикам или когда ошибка в одной зоне несёт больший риск, чем остальная часть приложения. Код биллинга часто меняют осторожнее, потому что ошибки бьют по доверию. Внутренний admin tool или worker для уведомлений могут обновляться быстрее. Такое разделение имеет смысл. Если одни и те же два человека выкатывают всё вместе каждую пятницу, лишние сервисы могут только добавить накладные расходы.
Большинство команд держит слишком много оборудования «на всякий случай». Эта привычка быстро становится дорогой. Вторая очередь, кеш или пул воркеров должны отвечать на один прямой вопрос: что сломается, если их убрать?
Помогает короткий тест. Оставляйте компонент, если он выдерживает нагрузку, которую основное приложение не может принять, предотвращает сбой, который ударит по платящим пользователям, изолирует код или данные, где нужен более жёсткий контроль, или позволяет одной команде выпускать изменения, не дожидаясь другую. Если он не делает ничего из этого, скорее всего, это просто оставшееся архитектурное наследие.
Убирайте осторожно, а потом неделю следите за ошибками, задержкой и обращениями в поддержку. Это скажет больше, чем вечное хранение запасных частей.
Простой пример из растущей SaaS-команды
Команда SaaS из восьми человек готовилась к запуску и приняла набор быстрых решений, которые в тот момент казались безопасными. Они добавили очередь для фоновых задач, подняли отдельный сервис воркеров и подключили второй инструмент поиска, потому что боялись, что основная база данных не справится.
Запуск прошёл нормально. Трафик рос несколько недель, а потом стабилизировался. Через шесть месяцев использования было меньше, чем в месяц запуска, но лишние части по-прежнему работали днём и ночью. Никто их не трогал, потому что внешне ничего не ломалось.
Вот так и закрепляется лишнее. Сервис, который был разумен под давлением, продолжает выставлять счёт ещё долго после того, как давление исчезло.
Когда команда наконец пересмотрела стек, первым сюрпризом стал поиск. Продукту были нужны только простые фильтры, несколько текстовых совпадений и сортировка по дате. Их основная база данных уже умела это делать. Они вернули поиск в базу, убрали отдельный search service и избавились ещё от одной системы, которой нужны были резервные копии, алерты и обновления.
Вторым сюрпризом стала настройка воркеров. Один старый воркер существовал только потому, что когда-то одна launch-фича требовала тяжёлой обработки. К тому моменту такие задачи стали редкими. Основное приложение могло обрабатывать их в непиковые часы, поэтому команда убрала старый воркер и лишние вычисления, которые шли вместе с ним.
Потом они посмотрели на очереди. Их было две. Одна очередь обрабатывала письма и сбросы пароля, и её стоило оставить. Другая отправляла крошечное число задач низкого приоритета каждый день и большую часть времени ничего не делала. Эти задачи объединили в ту же очередь, а вторую удалили.
Счёт уменьшился ещё до того, как кто-то обратился в procurement. Никаких переговоров о скидке, никаких долгих переписок с вендором, никаких специальных контрактов. Экономия пришла от удаления того, что больше не заслуживало своего места.
Такая чистка часто работает быстрее, чем поиск более низкой ставки. И она ещё делает продукт проще в эксплуатации. Чем меньше сервисов, тем меньше панелей, алертов в 2 ночи и странных сбоев между системами.
Вот почему опытные CTO обычно начинают с карты сервисов, а не с таблицы цен. Если инструмент почти ничего не делает или дублирует то, что у вас уже есть, его обычно первым и стоит поставить под вопрос.
Частые ошибки, из-за которых расходы остаются высокими
Многие команды пытаются сократить облачные расходы, уменьшив самый заметный пункт в счёте. Обычно это production compute. Это кажется практичным, но часто не трогает настоящее лишнее.
Одна частая ошибка — урезать production-реплики, не проверив, что именно они защищают. Если у приложения слабый failover, одна база данных или нет проверенного плана восстановления, сокращение реплик может одновременно и сэкономить деньги, и повысить риск. Во многих стеках больший перерасход сидит в другом месте: дублирующие воркеры, старые сервисы, которыми никто не пользуется, или очереди, которые продолжают работать при почти нулевом трафике.
Staging тоже создаёт проблемы. Команды часто делают его размером с production, а потом оставляют работать днём и ночью месяцами. Это имеет смысл, если вы каждый день тестируете под нагрузкой. Большинство команд этого не делает. Меньшее окружение, которое включается только тогда, когда оно нужно, обычно выполняет ту же задачу за гораздо меньшие деньги.
Работа по чистке ещё и игнорируется, потому что за неё никто не отвечает. Лишние системы мониторинга остаются. Старые сервисы feature flags остаются. Второй message broker остаётся, потому что одна команда попробовала его в прошлом году и не удалила. Каждый инструмент по отдельности может казаться дешёвым. Вместе они превращаются в постоянную ежемесячную утечку.
Та же слепая зона есть в логах, резервных копиях и лицензиях на софт. Команды считают серверы и забывают обо всём вокруг них. Логи быстро растут, особенно если приложение шумное или включён debug mode. Резервные копии копятся. Managed databases добавляют хранилище, IOPS, снимки и плату за передачу. Инструменты безопасности, observability и CI добавляют лицензионные расходы, которые никогда не видно в простом подсчёте серверов.
SaaS-команда может считать, что работает экономно, потому что её app servers выглядят маленькими. А более внимательный взгляд показывает хранение логов за 90 дней, крупные снимки базы в двух регионах, платные места в трёх пересекающихся инструментах и staging-кластер, который зеркалит production, хотя по выходным им никто не пользуется. Вот туда и уходят деньги.
Финансы обычно замечают проблему слишком поздно. Тогда разговор быстро сводится к просьбам о скидке и давлению на вендора. Procurement может помочь, но он не исправит архитектуру, которая дважды платит за одну и ту же работу. Кто-то со стороны техкоманды должен взять разбор на себя, решить, что остаётся, и убрать то, что больше не заслуживает своего места.
Команды, которые тратят меньше, делают одну простую вещь хорошо: они проверяют расходы на архитектуру до того, как месячный счёт заставит начать разговор.
Быстрые проверки, прежде чем звонить в procurement
Procurement может помочь, но скидки редко исправляют раздутый стек. Прежде чем просить более низкий тариф, проверьте, не платите ли вы за части системы, которые уже не заслуживают своего места. Удаление одного сервиса часто даёт больше экономии, чем длинный разговор о ценах.
Начните с нескольких прямых вопросов. Может ли один сервис выполнять работу двух платных инструментов? Каждая ли реплика действительно читает данные каждый день, или она просто стоит «на всякий случай»? Каждая ли очередь защищает пользователей от пиков, или она только добавляет задержку? Можно ли выключать dev, staging или demo-системы ночью и в выходные? Сэкономит ли месяц чистки больше, чем небольшое снижение ставки?
Дублирующие инструменты встречаются часто. Команда добавляет один сервис для логов, другой для алертов и третий для uptime, а потом обнаруживает, что облачный провайдер или уже существующий стек и так закрывает большую часть этого. Перекрытие выглядит безобидно, потому что каждый отдельный счёт небольшой. Но вместе это уже не мелочь.
С репликами нужна та же честность. Если реплика базы существует ради read-трафика, проверьте этот read-трафик. Если дашборды показывают почти нулевое реальное использование, реплика — это удобство, а не необходимость. То же касается лишних очередей. Некоторые очереди сглаживают всплески и поддерживают стабильность приложения. Другие просто переносят работу на несколько секунд позже и усложняют поиск сбоев.
Неproduction-системы тратят деньги самым скучным образом: они остаются включёнными весь день, каждый день. Если staging никому не нужен после рабочего времени, планируйте его выключение. Если demo-окружения простаивают днями, выключайте их по умолчанию и запускайте только тогда, когда они нужны. Одно это изменение может дать больше, чем скидка от вендора.
Помогает простое сравнение. Сложите ежемесячную стоимость дублирующих инструментов, простаивающих реплик и постоянно включённых нерабочих систем. Потом прикиньте, сколько сэкономит реалистичная скидка за тот же месяц. Если цифра от чистки больше, сначала делайте именно её.
Представьте маленькую SaaS-команду с одной ненужной репликой, двумя пересекающимися платными инструментами и staging-стеком, который работает всю ночь. Чистка этого может срезать сотни или тысячи долларов в месяц. А 5% скидки от старого счёта может даже не хватить, чтобы догнать эту экономию.
Обращайтесь в procurement после этого разбора, а не до него. Вам нужна лучшая цена на компактный стек, а не скидка на лишнее, которое вы решили оставить.
Что делать дальше
Начните с одного клиентского сценария, а не со всей платформы. Выберите что-то простое для отслеживания, например от регистрации до первой оплаты или от заказа до письма с подтверждением. Проведите этот путь через каждый сервис, очередь, базу данных, кеш и реплику, к которым он обращается. Обычно вы быстрее увидите лишнее в одном реальном сценарии, чем в широком архитектурном обзоре, который всё равно не успевает закончиться.
Поставьте чёткую цель по расходам на следующие 30 дней. Сделайте её достаточно конкретной, чтобы пришлось делать выбор, например сократить инфраструктурные расходы на 10% или удержать следующий месяц ниже фиксированной суммы. Если за это никто не отвечает, аудит превращается в красивый документ и не более.
Первый проход держите коротким. Проследите один клиентский путь от начала до конца и запишите каждый компонент, который он использует. Отметьте один дублирующий сервис, который можно безопасно убрать на этой неделе. Перечислите каждую реплику и очередь и рядом запишите, какую проблему она решает сегодня. После изменения сравните следующий счёт с текущим.
Последний шаг очень важен. Команды часто что-то удаляют, думают, что экономия сама появится, и идут дальше. Проверьте счёт ещё раз. Если сервис всё ещё указан, выясните почему. Возможно, старое окружение всё ещё работает. Возможно, логи всё ещё отправляются дважды. Возможно, очередь всё ещё нужна для одной устаревшей задачи, которую следовало перенести ещё несколько месяцев назад.
Будьте строги с репликами и очередями. Некоторые заслуживают своего места, потому что защищают загруженную базу или сглаживают реальные всплески трафика. Другие просто стоят там потому, что когда-то их было безопасно добавить, а потом неудобно задавать вопросы. Если read replica почти не обрабатывает чтения, запишите это. Если очередь только гоняет мелкие задачи раз в несколько часов, тоже запишите это. Расходы чаще следуют привычке, чем нагрузке.
Простое правило помогает: оставляйте то, что защищает выручку, доступность или время восстановления. Убирайте то, что защищает только старые предположения.
Если вам нужен внешний разбор, Oleg Sotnikov пишет об очистке такой архитектуры на oleg.is и помогает стартапам и небольшим командам принимать более экономные решения по инфраструктуре. Второе мнение помогает убрать внутренние споры и яснее увидеть, какие изменения безопасны уже сейчас.
Часто задаваемые вопросы
Что обычно заставляет расходы на облако расти раньше трафика?
Лишние компоненты. Команды добавляют очереди, реплики, воркеры и платные инструменты в загруженные моменты, а потом забывают их убрать. Каждый такой элемент добавляет вычисления, хранилище, логи, резервные копии и время инженеров.
Стоит ли обращаться к procurement до очистки архитектуры?
Нет. Сначала проверьте стек. Более низкий тариф немного поможет, но удаление одного неиспользуемого сервиса или простаивающей реплики часто экономит больше каждый месяц.
Как быстро найти дублирующие сервисы?
Проследите один обычный путь клиента от клика до ответа. Запишите все сервисы, очереди, базы данных и инструменты, которых он касается. Если две системы делают одну и ту же работу или одна почти не запускается, это повод задать вопросы.
Когда очередь всё ещё оправдана?
Оставляйте очередь, когда работа приходит рывками и приложению нужно время, чтобы догнать нагрузку. Отправка писем, импорт, повторные попытки и обработка изображений часто подходят. Если задания идут ровно весь день и основной app может справиться сам, очередь может только добавлять расходы и задержки.
Как понять, стоит ли оставлять read replica?
Только если реальный read-трафик действительно в ней нуждается или этого требуют ваши цели по доступности. Проверьте 30 дней чтений и использование CPU. Если большую часть дней реплика почти пустует, вы, скорее всего, платите за спокойствие, а не за необходимость.
Что делать со staging, QA и demo-окружениями?
Выключайте их, когда ими никто не пользуется. Большинству команд не нужны полноразмерные нерабочие среды, которые работают ночью и в выходные. Запланированное выключение может заметно сократить расходы без влияния на production.
Микросервисы — это причина более высокого счёта?
Не сами по себе. Отдельные сервисы полезны, когда разные команды выпускают изменения по разным графикам или одному участку нужна более строгая изоляция, например billing. Если одни и те же люди выкатывают всё вместе, лишние сервисы часто только создают накладные расходы.
Как проверить облачные расходы без большого аудита?
Выберите один путь клиента и занесите каждый компонент в таблицу с четырьмя пометками: что он делает, как часто запускается, сколько стоит и что сломается, если его выключить. Этого обычно достаточно, чтобы сделать первые безопасные сокращения.
Как безопаснее всего убрать архитектурное лишнее?
Убирайте по одному элементу и несколько дней следите за ошибками, задержкой и обращениями в поддержку. Объедините одну очередь, удалите одного воркера или уменьшите одну реплику. Маленькие изменения проще проверить и проще откатить.
Когда стоит пригласить внешнего CTO для разбора стека?
Привлекайте такого специалиста, когда команда не может договориться, что оставить, или когда никто не отвечает за чистку. Внешний разбор поможет построить один путь к выручке, показать, какие части всё ещё заслуживают своего места, и сократить расходы без догадок.