Разделы документации
ОбзорБыстрый стартРедакции и возможностиМодели и поляРедактор контентаМедиатекаЛокализацияПубликация и работа командыAPI, SDK и генерация типовРасширения и инструментыРабочие проектыЗадания, вебхуки и наблюдаемостьАудит и управление даннымиСоветники и доверие к плагинамКорпоративный входПространства, квоты и масштабированиеCommerce и PortalПрава и безопасностьРазвёртывание и обновленияЛицензии и установка пакетовТекущие ограниченияПомощь и диагностикаДанные в кабинетеCore CMSDeveloper PlatformProduction UseWorkflowOperationsComplianceAI AssistantsPlugin TrustEnterprise IdentityEnterprise ScaleEnterprise DeploymentCommerce BundlePortal BundleNotty CMS DocumentationAuth & SecurityContent ModelingDeploymentEcosystem & Packaging ConventionsEditions and First-party ModulesExtensibilityGetting StartedMedia ManagementModule Extraction PathDraft & PublishUpgrade GuideWebhooks & IntegrationsCookbook: Blog with Next.jsCookbook: Custom PluginCookbook: Multilingual SiteOperations DocsBackup AutomationDeployment BlueprintsRunbook — Восстановление БД из бэкапаRunbook — Плановый деплойRunbook — Реакция на инцидентRunbook — Откат релизаRunbook — Горизонтальное масштабированиеRunbook — Ротация секретовRunbook — Major upgradeSecrets ManagementNotty CMS — Capability MapNotty Configuration ModelGenerated App ContractComponents and Dynamic ZonesMiddleware SystemPerformance & Scaling ToolkitDisaster Recovery PlaybookDistribution Model
Документация / Технический справочник

Runbook — Горизонтальное масштабирование

Техническое руководство из исходного проекта Notty. Примеры, параметры и эксплуатационные ограничения.

По функциям модуляОбновлено 2026-09-30

Когда: растёт latency, CPU/memory приближаются к limit'у, очередь job'ов накапливается. Цель — расширить ёмкость без переписывания.

Связанный документ: docs/scaling.md — performance toolkit (cache, read replicas, query guardrails, search adapters).

Diagnose (≤ 15 мин)

Чек до того как что-то трогать:

  • CPU/memory pod'ов: kubectl top pod -n notty или docker stats.
  • p95 latency: notty_http_request_duration_seconds.
  • DB: notty_db_slow_queries_total, notty_db_replica_fallbacks_total.
  • Cache: hit ratio = hits / (hits + misses). Цель > 80%.
  • Job queue: /api/admin/jobs/stats — растёт ли pending?
  • Внешние зависимости (Redis, S3, search) живы и без задержек.

Решение зависит от того, где боттлнек. Не масштабируйте app, если упирается в БД.

App tier — горизонтальное масштабирование

Kubernetes (HPA уже настроен)

deployment/kubernetes/hpa.yaml ставит min=2, max=10, target CPU 70%, memory 80%. Реакция автоматическая. Если вручную:

kubectl -n notty scale deploy/notty --replicas=6
kubectl -n notty rollout status deploy/notty

При переходе с 1 → N нужно убедиться, что у вас:

  • общий БД-конект-пул (managed PG с max_connections >= replicas * pool_size);
  • shared-кэш (Redis adapter) — иначе каждый pod строит свой кэш с нуля и cache_misses_total всплывает на rollout'ах. См. scaling.md, раздел Redis-adapter;
  • объектное хранилище (STORAGE_TYPE=s3|...), не локальный volume.

docker-compose

docker-compose.yml рассчитан на одну реплику. Для горизонтального запуска поднимайте Notty за внешним балансировщиком (Caddy/Cloudflare Load Balancing) и держите stateful слои (PG, Redis, MinIO/S3) общими. Поднимать одного notty сервиса с deploy.replicas в compose возможно только в Swarm.

Database tier — read replicas

DATABASE_REPLICA_URLS=postgres://...@replica-1:5432/notty,postgres://...@replica-2:5432/notty

Перезапустите Notty, проверьте:

  • notty_db_replica_fallbacks_total — стабильно низкий;
  • p95 latency на read-эндпоинтах падает.

Запись остаётся на primary. Locking SELECT FOR UPDATE, advisory locks и nextval/setval сами уезжают на primary (см. scaling.md).

Cache tier — Redis

In-process кэш (default) хорош для одного pod'а. На N pod'ах:

  1. Поднимите managed Redis (или kubernetes-statefulset с PVC).
  2. Подключите Redis-адаптер кэша через плагин (см. docs/scaling.md).
  3. Прокиньте REDIS_URL в env Notty.
  4. Перезапустите. Hit ratio должен подняться обратно к 80%+.

Search tier — внешний движок

Если Content API замедляется на полнотекстовом поиске (q=...) на >100k документов:

  • подключите Meilisearch / Typesense / Elasticsearch адаптер (см. docs/scaling.md, раздел Search adapters);
  • запустите getSearchService().reindex(<contentType>) для перевода корпуса.

Job tier

При росте pending job'ов:

  • in-process queue хорош до десятков RPS на job. Дальше — Redis-backed адаптер (packages/server/src/lib/jobs/queue.ts).
  • проверьте, не залип ли конкретный обработчик: GET /api/admin/jobs?status=running — поминутный slice по started_at. Если есть задачи > 30 мин — это баг обработчика, scale не поможет.

Что нельзя делать «для перформанса»

  • Отключать query guardrails. Они спасают от случайных deep-pagination и populate-bombs.
  • Выключать rate limiting в проде.
  • Складывать media в local volume на нескольких репликах одновременно.
  • Удалять statement_timeout — это страховка против runaway-запросов.

После масштабирования

  • Обновили minReplicas / maxReplicas в HPA, если это устойчивая нагрузка.
  • Подтвердили connection pool в managed PG (max_connections ≥ replicas * pool_size + admin/cron headroom).
  • Зафиксировали изменение в operations log.
  • Если изменение временное (event/распродажа) — поставили задачу обратно масштабироваться вниз.

Источник: docs/operations/runbooks/scale-out.md. Снимок документации исходного проекта. Технический справочник сохраняет язык оригинала.