Проект, начавшийся на одном виртуальном сервере (VPS/VDS), обычно растет быстрее, чем инфраструктура. Сначала хватает «поднять тариф», затем появляются всплески задержек, ошибки 5xx, падения базы данных из-за нехватки памяти или «зависания» при дисковых операциях. В этот момент часто выбирается между двумя путями: вертикальным масштабированием (дать одному узлу больше ресурсов) и горизонтальным масштабированием (разнести нагрузку на несколько узлов). Ошибка на этом этапе обычно стоит дорого: неправильный апгрейд не убирает узкое место, а преждевременный «распил» на множество серверов приносит сложность и новые точки отказа.

Ниже приведен прикладной сценарий, рассчитанный на типовую архитектуру «веб-приложение + база данных» на VPS/VDS: как найти bottleneck, как обосновать выбор между вертикальным и горизонтальным ростом, как подойти к шардированию без импровизации и как оценить цену простоя так, чтобы стратегия масштабирования была привязана к бизнес-риску, а не к ощущениям.
Содержание
- Шаг 0. Зафиксировать «что считается проблемой»: SLO, деградация и простои
- Поиск bottleneck: диагностика по слоям, а не по догадкам
- Вертикальное масштабирование на VPS/VDS: быстрый выигрыш с понятными пределами
- Горизонтальное масштабирование: не «модно», а необходимо при определенных рисках
- Промежуточная стратегия: масштабирование без «микросервисов»
- Шардирование: как подготовить стратегию, чтобы не «разорвать» данные
- Цена простоя: расчет, который помогает выбрать между «апгрейдом» и «архитектурой»
- Как связать результаты диагностики с выбором стратегии
- План на 30 дней: от диагностики до обоснованного масштабирования
- Вывод: решение начинается с bottleneck и заканчивается экономикой риска
Шаг 0. Зафиксировать «что считается проблемой»: SLO, деградация и простои
Масштабирование имеет смысл только тогда, когда понятно, какая цель преследуется. В реальных внедрениях полезно начать с простых определений:
- SLO по задержке: например, P95 ответа API не выше 300 мс при пиковой нагрузке
- SLO по ошибкам: например, доля 5xx не выше 0,1%
- Окно пика: конкретные часы/дни, когда система должна выдерживать максимум
- RTO (сколько времени допустимо восстанавливаться) и RPO (сколько данных допустимо потерять)
Эта фиксация нужна по двум причинам. Во‑первых, «медленно» и «падает» превращаются в измеримые критерии. Во‑вторых, становится возможным осознанно сравнить: дешевле ли увеличить ресурсы одного VPS, или оправдана архитектура, допускающая отказ узла без простоя.
Поиск bottleneck: диагностика по слоям, а не по догадкам
Узкое место в системе на VPS/VDS редко находится там, где «кажется». Высокий Load Average может быть следствием диска, а рост CPU – следствием логирования или неудачного SQL. Практический подход – двигаться сверху вниз и фиксировать признаки на каждом уровне: пользовательская симптоматика → приложение → база/кэш → ОС → виртуализация/железо.
1. Симптомы: задержка, ошибки, нестабильность
Сначала полезно разделить ситуации:
- Задержка растет, ошибок мало – часто упирается в CPU, блокировки в БД, нехватку соединений, насыщение диска или сети
- Ошибки растут вместе с задержкой – частый признак исчерпания ресурса (RAM/FD/conntrack), падения upstream-сервисов, таймаутов, перезапусков
- Система «пилит» (то нормально, то плохо) – нередко связанно с GC, кроном/бэкапами, «шумными соседями» на виртуализации, троттлингом диска/CPU
Если сбор метрик отсутствует, минимальный набор для старта – системные метрики (CPU/RAM/disk/net), метрики приложения (RPS, latency P95/P99, error rate) и метрики базы (время запросов, блокировки, количество соединений). Без этого выбор между вертикальным и горизонтальным масштабированием превращается в лотерею.
2. ОС и виртуализация: что часто «ломает картину» на VPS
На VPS/VDS есть особенности, которые маскируют bottleneck:
- CPU steal time – часть времени CPU «отобрана» гипервизором. В top может появляться %st, в mpstat – steal. Высокий steal означает, что приложение тормозит не из‑за собственного кода, а из‑за конкуренции за физические ядра
- Троттлинг диска – на некоторых платформах лимиты IOPS/throughput приводят к резким скачкам await и росту iowait
- Неравномерная производительность – «в среднем нормально», но в пике появляются хвосты по задержке. Для веб‑проектов важнее P95/P99, чем среднее
При подозрении на влияние виртуализации полезно сопоставить: нагрузку приложения, системные метрики и графики задержек. Если приложение без изменений «плывет» в разные дни при одинаковом трафике, это повод проверить steal/IO latency, а также рассмотреть VDS с гарантированными ресурсами.
3. Быстрая локализация узкого места: чек‑лист по ресурсам
CPU
- Признаки: высокий user/system, рост очереди запросов, падение RPS при росте latency, частые контекстные переключения
- Что смотреть: top/htop, mpstat -P ALL 1, pidstat 1, метрики контейнеров (если используются)
- Типовые причины: тяжелая сериализация/шифрование, компрессия, некорректные индексы (CPU «горит» на планировании/агрегациях), избыточное логирование, слишком частые фоновые задачи
RAM
- Признаки: рост latency при старте swap, OOM-killer, частые рестарты процессов, деградация БД из‑за вытеснения page cache
- Что смотреть: free -m, vmstat 1 (si/so), dmesg на события OOM, RSS процессов
- Типовые причины: утечки памяти, слишком большой work_mem/sort_buffer, «раздутые» кэши, отсутствие лимитов на фоновые воркеры
Диск (IOPS/latency)
- Признаки: высокий iowait, «ступеньки» в latency, зависания при бэкапах, резкий рост времени запросов в БД
- Что смотреть: iostat -x 1 (await, %util), iotop, графики latency на уровне хранилища (если доступны)
- Типовые причины: fsync на каждом запросе из‑за настроек, нехватка IOPS, конкуренция процессов (БД + бэкап + логирование), некорректный режим journaling, переполненные очереди записи
Сеть
- Признаки: таймауты между сервисами, рост retransmits, проблемы с TLS‑handshake, очереди на балансировщике, ошибки 502/504
- Что смотреть: ss -s, netstat -s (retransmits), графики pps/битрейт, conntrack (если NAT/файрвол)
- Типовые причины: исчерпание ephemeral ports на исходящих соединениях, слишком агрессивные таймауты, перегретый conntrack, лимиты на соединения в БД/кэше
Лимиты ОС
- Признаки: «too many open files», странные отказы при пике, падения воркеров
- Что смотреть: ulimit -n, лимиты systemd, /proc/sys/net/ (somaxconn, backlog), nf_conntrack_count/nf_conntrack_max
4. Приложение и база: bottleneck часто не «в железе»
Даже при очевидной нехватке CPU/RAM полезно проверить прикладные причины: один неудачный запрос способен «съесть» ресурсы так, что никакой апгрейд VPS не даст эффекта.
База данных (PostgreSQL/MySQL)
- Медленные запросы: включение slow log (MySQL) или pg_stat_statements (PostgreSQL), поиск запросов с высокой суммарной стоимостью, анализ планов через EXPLAIN (ANALYZE)
- Блокировки: в PostgreSQL – pg_locks и ожидания; в MySQL – диагностика InnoDB и ожиданий метаданных
- Соединения: исчерпание connection limit выглядит как «внезапные» ошибки при росте трафика. Часто лечится пулером (например, PgBouncer) раньше, чем масштабированием железа
- Автовакуум/фоновая очистка: в PostgreSQL неправильно настроенный autovacuum способен устроить «плавающие» задержки в пике
Кэш и очереди
- Промахи кэша приводят к лавинообразному росту нагрузки на БД (cache stampede). В таком сценарии масштабирование БД без стабилизации кэша дает временный эффект
- Очереди (background jobs) при отставании создают «долг», который затем выливается в пик нагрузки на БД/диск
Практический критерий «это точно инфраструктура, а не код»: после оптимизации топ‑запросов и ограничения фоновых задач метрики все равно упираются в один и тот же ресурс (CPU/IO/RAM) на предсказуемом уровне нагрузки.
Вертикальное масштабирование на VPS/VDS: быстрый выигрыш с понятными пределами
Вертикальное масштабирование – увеличение ресурсов одного узла: vCPU, RAM, диска, иногда – переход на более предсказуемый профиль CPU/IO. Для небольших и средних проектов это часто самый экономичный и быстрый шаг, если соблюдаются условия.
Когда вертикальный рост оправдан
- Узкое место – в одном ресурсе, и его можно измерить: CPU стабильно в 90-100%, RAM регулярно уходит в swap, диск показывает высокую latency
- Архитектура пока монолитна, и разделение на узлы потребует времени на рефакторинг (например, хранение сессий, загрузка файлов, фоновые задачи)
- Требования к отказоустойчивости умеренные: допустим короткий простой на обслуживание или перезапуск при увеличении ресурсов
Ограничения вертикального пути
- Единственная точка отказа: один VPS остается критическим узлом. Даже если ресурсов хватает, риск простоя из‑за ОС, диска или сбоя на стороне платформы не исчезает
- Потолок по ресурсу: рано или поздно упирается в максимальный план или экономическую целесообразность
- Не все апгрейды «безостановочные»: увеличение RAM/CPU иногда требует перезагрузки, что напрямую влияет на RTO
- Непредсказуемость общего VPS: при высокой доле steal time вертикальный апгрейд может не дать линейного прироста
Что сделать до апгрейда ресурсов (часто дает эффект без масштабирования)
- Проверить лимиты: файловые дескрипторы, backlog, conntrack
- Включить и разобрать медленные запросы, добавить индексы, убрать N+1, сократить объемы возвращаемых данных
- Настроить пул соединений к БД, ограничить воркеры фоновых задач
- Разнести бэкапы и тяжелые джобы по времени, исключить конкуренцию с пиком
Если после этих шагов bottleneck остается в ресурсе и прогнозируемо растет вместе с нагрузкой, вертикальное масштабирование дает понятный результат и минимальные изменения в коде.
Горизонтальное масштабирование: не «модно», а необходимо при определенных рисках
Горизонтальное масштабирование – добавление узлов и распределение нагрузки. В контексте VPS/VDS это чаще всего означает: несколько виртуальных серверов под приложение, отдельный узел под базу, выделенный кэш, балансировщик, реплики для чтения. Такой путь дороже в эксплуатации, но решает задачи, которые вертикальный апгрейд не закрывает.
Сигналы, что пора масштабироваться горизонтально
- Простой слишком дорог: требования по доступности выше, чем способен дать один узел
- Не один bottleneck: при росте ресурсов начинает «вылазить» следующий лимит (сначала CPU, затем IO, затем лимит соединений), а нагрузка уже близка к уровню, где ошибка стоит дорого
- Появились разные профили нагрузки: фронтенд/API упираются в CPU, БД – в диск, фоновые задачи – в RAM. На одном VPS такие профили мешают друг другу
- Нужны изоляция и управляемость: отдельные окна обслуживания, отдельные политики бэкапа, предсказуемое влияние изменений
Базовый «горизонтальный минимум» для проекта на VPS
На практике часто начинается не с «десятков узлов», а с разделения ролей:
- Балансировщик (Nginx/HAProxy) + 2 узла приложения (stateless)
- Отдельный VPS/VDS под БД с диском нужного профиля
- Отдельный кэш (Redis/Memcached) при выраженной нагрузке на чтение
Такой шаг уже дает: возможность катить обновления по очереди, снижать влияние пиков на БД и уменьшать вероятность «падения всего». При этом сложность остается управляемой.
Где горизонтальное масштабирование добавляет риски
- Сетевые задержки становятся частью производительности: то, что на одном сервере было «в памяти», превращается в RPC и требует таймаутов, ретраев и наблюдаемости
- Появляется проблема состояния: сессии, загрузки файлов, кэш, фоновые задачи должны работать корректно на нескольких узлах
- Нужно управлять конфигурацией: инвентарь, секреты, деплой, мониторинг и алерты – на каждый узел
Поэтому горизонтальный рост обычно оправдывается не «желанием распределить», а измеримой ценой простоя и пределами вертикального пути.
Промежуточная стратегия: масштабирование без «микросервисов»
Существует распространенный компромисс: оставить приложение монолитным, но вынести тяжелые компоненты на отдельные VPS/VDS. Это особенно актуально для проектов, где кодовая база не готова к глубокому рефакторингу, но один сервер уже не справляется или стал слишком рискованной точкой отказа.
Пример последовательности без радикальной перестройки
- Вынести базу данных на отдельный узел и настроить резервное копирование с проверкой восстановления
- Добавить второй узел приложения и балансировщик. Сессии – в Redis или подписанные cookies; файлы – в объектное хранилище или общий том (с учетом рисков)
- Ввести реплику БД для чтения, если много read‑нагрузки и есть подходящие запросы (без строгой необходимости «свежести» данных)
- Отделить фоновые воркеры на отдельный VPS при тяжелых задачах (генерация отчетов, обработка изображений, рассылки)
При аренде VPS/VDS под дополнительные узлы важно учитывать не только цену, но и сетевую связность. Размещение серверов в одном регионе снижает задержку между приложением и БД; в ряде сценариев это критичнее, чем разница в паре процентов по стоимости. В качестве примера сервисов аренды виртуальных серверов есть VPS.house; при выборе площадки обычно оцениваются именно задержки, стабильность IO и прогнозируемость CPU.
Шардирование: как подготовить стратегию, чтобы не «разорвать» данные
Шардирование часто вспоминается слишком поздно – когда один сервер БД уже не справляется с записью или объем данных становится неподъемным для обслуживания (бэкапы, VACUUM, миграции, восстановление). При этом шардирование – не «ускоритель», а способ распределить пределы: по диску, по CPU, по lock contention, по размеру индексов и по времени обслуживания.
Сначала – убедиться, что шардирование действительно нужно
Перед тем как «резать» базу, обычно проверяются менее инвазивные шаги:
- Оптимизация запросов, индексация, уменьшение объемов данных в горячих таблицах
- Репликация (read replicas) и разделение чтения/записи
- Партиционирование внутри одной БД (например, по времени) – если проблема в обслуживании больших таблиц, а не в пределе по write‑throughput
- Очереди и батчинг для тяжелых операций записи
Если узкое место – именно запись и конкуренция за ресурсы одного инстанса, а рост данных делает восстановление слишком долгим относительно RTO, шардирование становится практической необходимостью.
Выбор shard key: главный проектный риск
Shard key определяет, как данные распределяются по шардам. Ошибка на этом этапе приводит к перекосам (hot shard) и сложностям с запросами. Ключ выбирается так, чтобы:
- Запросы были локальными: большинство операций работало в рамках одного шарда
- Нагрузка распределялась равномерно: отсутствие «особых» пользователей/организаций, которые концентрируют трафик на одном шарде
- Рост был предсказуемым: добавление шардов не требовало тотальной миграции данных
Для B2C‑сервисов часто подходит user_id, для B2B/SaaS – tenant_id (организация). Для логов и событий иногда выбирается комбинация «время + хэш» или отдельное хранилище, чтобы не смешивать OLTP и большие последовательные вставки.
Базовые схемы шардирования и их последствия
1. Range-based (диапазоны)
Данные распределяются по диапазонам ключа (например, user_id 1-1 000 000). Плюсы – простота маршрутизации и удобство для выборок по диапазону. Минусы – риск «горячего» последнего диапазона и сложность балансировки при неравномерном росте.
2. Hash-based (по хэшу)
Ключ хэшируется и раскладывается по шардам. Плюсы – равномерность распределения. Минусы – сложнее делать запросы по диапазонам, а расширение числа шардов требует продуманной стратегии (например, consistent hashing или виртуальные «бакеты»).
3. Directory-based (каталог/таблица маршрутизации)
Отдельный сервис/таблица знает, где лежат данные конкретного клиента/пользователя. Плюсы – гибкость (крупного клиента можно переносить отдельно). Минусы – появляется критичный компонент «каталог», который требует отказоустойчивости и кэширования.
Маршрутизация запросов: где хранится логика
Есть два распространенных подхода:
- В приложении: библиотека/слой доступа к данным выбирает шард по ключу. Это прозрачно для инфраструктуры, но усложняет миграции и требует дисциплины разработчиков
- Через прокси/роутер: внешний слой направляет запросы на нужный шард. Это упрощает стандартизацию, но добавляет сетевой хоп и отдельную точку, которую нужно масштабировать и мониторить
В обоих случаях критично заранее определить: какие запросы допускаются без ключа шардирования. Запросы «по всем данным» (global queries) почти всегда становятся источником деградации и должны быть вынесены в аналитический контур.
Транзакции и согласованность: что ломается при шардировании
- Cross-shard транзакции в классическом ACID‑виде становятся дорогими и сложными. Часто применяется подход «саги», идемпотентность и компенсационные операции
- Уникальные идентификаторы: автоинкремент перестает быть глобальным. Используются UUID, Snowflake‑подобные генераторы или диапазоны ID на шард
- Join между шардами в OLTP становится непрактичным. Схема данных обычно меняется в сторону денормализации или «read model» (материализованные представления, отдельные поисковые индексы)
Эти ограничения – причина, почему шардирование следует начинать с четкого описания доменных границ: «какие данные должны жить вместе» и «какие операции обязаны быть атомарными».
План расширения: как избежать «тотального переселения»
Шардирование, рассчитанное только на текущие 2-3 узла, быстро превращается в ловушку. В промышленной практике используются приемы, позволяющие добавлять шарды без миграции половины базы за один раз:
- Виртуальные шарды (бакеты): логических сегментов больше, чем физических узлов; при добавлении узла часть бакетов переносится
- Consistent hashing: снижает объем перераспределения при изменении числа шардов
- Онлайн‑миграция: двойная запись на старый и новый шард на время переноса, валидация, переключение чтения, затем отключение старого пути
Под такие операции заранее закладываются метрики миграции, контроль целостности и бэкапы на уровне каждого шарда.
Цена простоя: расчет, который помогает выбрать между «апгрейдом» и «архитектурой»
Вопрос «вертикально или горизонтально» упирается не только в технику, но и в стоимость риска. Цена простоя – это не абстракция, а инструмент для определения допустимых затрат на отказоустойчивость и скорость масштабирования.
Что считать простоем
- Полный downtime: сервис недоступен (ошибки, невозможность совершить ключевое действие)
- Деградация: сервис отвечает, но медленно; конверсия и удержание падают. Для многих проектов деградация стоит почти так же дорого, как падение
- Частичная недоступность: недоступны платежи, личный кабинет, поиск – потери зависят от критичности функции
Базовая модель расчета (упрощенная, но рабочая)
Для оценки берутся измеримые компоненты:
- Потерянная выручка за время простоя: средняя выручка/час в пике × длительность
- Потерянная маржа (если затраты на товар/логистику важны): выручка × маржинальность
- Компенсации/штрафы по SLA (для B2B)
- Операционные затраты: время инженеров, поддержка, разбор инцидента, горячие фиксы
- Долгосрочный эффект: отток пользователей, репутационные потери (сложно мерить, но важно хотя бы оценочно)
Пример расчета (числа условные, методика – прикладная):
Пиковая выручка – 120 000 ₽/час, маржинальность – 40%, средняя длительность инцидента – 1,5 часа, стоимость привлечения/удержания клиента в среднем добавляет 20 000 ₽ косвенных потерь на инцидент, работа команды – 15 000 ₽.
Тогда прямые потери маржи: 120 000 × 0,4 × 1,5 = 72 000 ₽.
Итого с косвенными и операционными: 72 000 + 20 000 + 15 000 = 107 000 ₽ на один инцидент.
Если подобная ситуация происходит хотя бы 2 раза в месяц, ожидаемые потери уже около 214 000 ₽/мес. На этом уровне становится проще обосновать расходы на резервирование (дополнительные VPS/VDS, репликацию, автоматизацию деплоя и мониторинг), чем бесконечно «докручивать» один сервер.
Ожидаемый риск: как привязать бюджет к вероятности
Для управленческого решения полезна формула ожидаемого ущерба:
Ожидаемый ущерб = вероятность инцидента × стоимость инцидента.
Вероятность можно оценивать на основе истории (сколько раз в квартал происходили простои/деградации) и текущей нагрузки (насколько близко система к пределам). Даже грубая оценка помогает избежать крайностей: как чрезмерной экономии, так и преждевременного усложнения архитектуры.
Как связать результаты диагностики с выбором стратегии
Ниже приведена практическая логика принятия решения, которая работает для большинства проектов на аренде VPS/VDS.
Если bottleneck – CPU, но БД и диск в порядке
- Краткосрочно: вертикальный апгрейд CPU/частоты, оптимизация горячих участков кода, кэширование, уменьшение логирования
- Среднесрочно: несколько узлов приложения + балансировщик (горизонтально), при условии stateless‑подхода
Если bottleneck – RAM и swap/oom
- Краткосрочно: увеличить RAM, ограничить воркеры, настроить пул соединений, проверить утечки памяти
- Среднесрочно: вынести кэш/очереди/воркеры на отдельные узлы, чтобы память перестала быть общим «мешком» для всех процессов
Если bottleneck – диск и latency (особенно на БД)
- Краткосрочно: перейти на более быстрый профиль диска, уменьшить fsync‑нагрузку корректными настройками, оптимизировать индексы и запросы
- Среднесрочно: вынести БД на отдельный VPS/VDS, добавить реплики для чтения, пересмотреть бэкапы и тяжелые операции
- Долгосрочно: подготовка к шардированию, если запись и объем данных продолжают расти
Если ключевой риск – простой, а не производительность
- Сразу: горизонтальные элементы для отказоустойчивости (минимум два узла приложения, балансировщик, регулярные бэкапы, тест восстановления)
- Далее: реплика БД и сценарий аварийного переключения (failover) с понятным RTO
При добавлении узлов обычно учитывается география: размещение виртуальных серверов в одном регионе снижает задержки и упрощает синхронизацию. Например, при необходимости быстро расширить пул серверов в одном городе можно взать аренду VPS в Москве как один из вариантов, если нагрузка чувствительна к RTT между приложением и базой.
План на 30 дней: от диагностики до обоснованного масштабирования
Для проектов, которые уже уперлись в предел одного VPS/VDS, удобен короткий план работ, минимизирующий риск «перестраивать наугад».
Неделя 1: наблюдаемость и воспроизводимость
- Сбор метрик CPU/RAM/disk/net, latency P95/P99, error rate
- Включение slow log/статистики запросов в БД, сбор блокировок и количества соединений
- Фиксация SLO, RTO/RPO и «часов пика»
Неделя 2: устранение очевидных ограничений
- Лимиты ОС (FD, backlog, conntrack), таймауты, пул соединений
- Топ‑запросы: индексы, переписывание, кэширование горячих чтений
- Разнесение бэкапов/джобов по времени, ограничение параллелизма воркеров
Неделя 3: выбор стратегии и пилот
- Если bottleneck четкий и один – вертикальный апгрейд и контроль метрик
- Если риск простоя высок – пилот горизонтального минимума (2 app‑узла + балансировщик), подготовка к выносу БД
- Нагрузочное тестирование (k6/wrk/аналог) для проверки гипотезы до продакшена
Неделя 4: подготовка к росту данных (если БД – ограничение)
- Репликация и план восстановления
- Оценка shard key и перечня запросов, которые должны быть локальными
- План миграции/онлайн‑переноса и требования к идемпотентности операций
Даже если шардирование не стартует сразу, подготовка (ключи, ограничения на запросы, дисциплина транзакций) обычно снижает стоимость будущей миграции на порядок.
Вывод: решение начинается с bottleneck и заканчивается экономикой риска
Для проекта на VPS/VDS выбор между вертикальным и горизонтальным масштабированием редко бывает идеологическим. На практике стратегия строится так:
- Сначала – измерение и локализация bottleneck по метрикам, устранение очевидных ограничений в приложении и БД
- Затем – вертикальный апгрейд, если узкое место однозначно и риск простоя приемлем
- Далее – горизонтальное разделение ролей и отказоустойчивость, если простои или деградации обходятся дороже, чем эксплуатация нескольких узлов
- Наконец – шардирование, когда пределы одного инстанса БД становятся системными и подтверждены нагрузкой, объемом данных и требованиями к RTO/RPO
Такой порядок позволяет масштабировать инфраструктуру на аренде VPS/VDS без спешки и без избыточной сложности – с опорой на измерения и расчет цены риска.





