MAATRIX / Блог / Сколько RAM нужно для Payload CMS

Сколько RAM нужно для Payload CMS

MAATRIX

Payload CMS продают как «TypeScript-first» headless-CMS, где схема контента описывается кодом, а не собирается мышкой в админке — это удобно разработчику, но обманчиво просто для того, кто планирует сервер под неё. В официальной документации нет чёткой цифры минимальной RAM, а форумы полны жалоб на упавший процесс ровно во время next build или после третьей загрузки изображений через media-коллекцию. Разберём, из чего на самом деле складывается память Payload: рантайм, сборка админки и база данных живут не по одним и тем же правилам, и если считать только «сервер вроде запустился» — легко промахнуться с тарифом.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Почему у Payload нет одной цифры RAM

Payload с версии 3.x — это не отдельный сервер, а пакет, который устанавливается прямо в Next.js-приложение: административная панель рендерится через App Router тем же процессом, что отдаёт ваш сайт или API. Отсюда и главная особенность потребления памяти — она не постоянна, а скачет между тремя разными режимами:

  • Разработка (next dev) — постоянно держит в памяти дерево модулей, кеш Fast Refresh, TypeScript-компилятор для payload.config.ts. Самый прожорливый режим, но он живёт только на вашей машине или CI, не на проде.
  • Сборка (next build) — кратковременный, но самый опасный пик: Next.js собирает статику, генерирует типы Payload из конфига коллекций, оптимизирует изображения через sharp. Именно здесь чаще всего падает процесс на маленьком VPS.
  • Продакшн-рантайм (next start или standalone-сервер) — самый лёгкий режим: держит уже собранные страницы и обслуживает API/админку по запросу.

Путать эти три цифры — типичная ошибка: сервер, который спокойно тянет рантайм на 1 ГБ, может не пережить деплой с пересборкой на том же объёме.

Node.js-процесс: что жрёт память само по себе

Пустое Node.js-приложение с подключённым Payload и парой коллекций в состоянии покоя занимает ориентировочно 200–350 МБ — это V8-heap плюс сам движок Payload (схема коллекций, access control, hooks, локализация, если включена). Цифра растёт с числом коллекций, полей richText (Lexical-редактор тянет собственное дерево узлов) и активных плагинов — official-плагины вроде @payloadcms/plugin-seo или plugin-search добавляют не так много, но каждый новый collection type с вложенными blocks увеличивает объём схемы, которую Payload держит в памяти для валидации.

Отдельная статья расходов — sharp, библиотека обработки изображений, которую Payload использует для генерации sizes (thumbnail, card, og-image и т.д.) при загрузке в media-коллекцию. Обработка одного крупного изображения (условно от 10-15 МБ, RAW-фото с телефона) может кратковременно потребовать несколько сотен мегабайт сверх базового потребления — это нормально для sharp, но на VPS с 1 ГБ RAM без swap такой скачок иногда роняет процесс через OOM killer.

# ограничить heap самого Node.js процесса Payload
NODE_OPTIONS="--max-old-space-size=1024" node server.js

Это не экономит память сама по себе, а задаёт потолок, при котором Node аккуратно освобождает память через garbage collector вместо неконтролируемого роста — полезно, чтобы процесс не тянул с собой соседние сервисы на общем сервере.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

База данных: Postgres против MongoDB по памяти

Payload 3.x поддерживает три адаптера БД — MongoDB, PostgreSQL и SQLite, и выбор напрямую влияет на бюджет RAM сервера.

АдаптерПамять БД в простоеОсобенности
SQLiteпрактически 0 (файл на диске)подходит для одиночных сайтов и MVP, но плохо переживает конкурентную запись
PostgreSQL~50–100 МБ на пустой базе, растёт с shared_buffersлучший баланс для продакшна, гибкие индексы для richText-полей
MongoDB~200–300 МБ в простоенативнее ложится на схему Payload (JSON-документы), но сама СУБД прожорливее

Если у вас уже есть PostgreSQL, настроенный на VPS, логично взять адаптер @payloadcms/db-postgres — вы получите привычные бэкапы и мониторинг и не добавите второй тяжёлый процесс на сервер. MongoDB имеет смысл, если проект изначально проектировался вокруг документной модели или мигрирует со старой версии Payload (2.x была MongoDB-only).

Для расчёта общего бюджета сервера: RAM Node.js-процесса и RAM базы данных не пересекаются, их нужно складывать, а не выбирать по большей. Плюс к этому — прослойка ОС, SSH, systemd, возможно nginx перед приложением: закладывайте на это отдельные 150–250 МБ.

Таблица минимальных конфигураций

Ориентировочные цифры для разных сценариев — реальное потребление зависит от числа коллекций, richText-полей, объёма и частоты загрузки медиа. Проверяйте на своём проекте через free -h и htop после недели работы под реальной нагрузкой.

СценарийRAMvCPUКомментарий
MVP / лендинг, SQLite, редкие правки2 ГБ1-2сборку лучше делать не на этом же сервере или заранее выделять swap
Блог/каталог, Postgres, до 10 коллекций4 ГБ2комфортный минимум для стабильной работы + сборка на месте
Средний проект, richText + media, активные редакторы8 ГБ2-4запас под пики sharp и параллельные запросы к админке
Крупный мультиязычный проект, MongoDB, много blocks-полей16 ГБ4+локализация и вложенные blocks заметно увеличивают вес схемы в памяти

Если проект живёт на одном сервере целиком (Payload + Postgres/Mongo + nginx), закладывайте на один уровень выше, чем «голый» рантайм — совмещённая установка почти всегда требует больше буфера, чем сумма минимумов по документации каждого компонента.

Как не словить OOM на сборке

Самая частая жалоба в комьюнити Payload — не «медленно работает», а «падает при деплое». Причина почти всегда одна: next build на сервере с 1-2 ГБ RAM и без свопа. Несколько практических приёмов:

  • Собирайте не на проде. Соберите приложение в CI (GitHub Actions, GitLab CI) или на отдельной build-машине, а на сервер выкатывайте уже готовый .next/standalone — рантайм после сборки требует в разы меньше памяти, чем сама сборка.
  • Добавьте swap, если сборка всё же идёт локально. Даже 2 ГБ файла подкачки не спасут от деградации по скорости, но спасут процесс от убийства OOM killer'ом в момент пика.
sudo fallocate -l 2G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
  • Ограничьте heap сборки явно, если процесс собирается прямо на сервере:
NODE_OPTIONS="--max-old-space-size=2048" npx next build
  • Проверьте параллелизм sharp. По умолчанию sharp может использовать несколько потоков для обработки изображений — на слабом сервере стоит ограничить это переменной окружения UV_THREADPOOL_SIZE или обрабатывать медиа партиями, а не заливать сотни файлов разом при первом импорте контента.

Если падения всё равно случаются на этапе рантайма, а не сборки — вероятно, дело не в Payload, а в общей нехватке памяти сервера; общий подход к диагностике описан в статье что делать при нехватке RAM.

Эксплуатация: connection pool, PM2 и мониторинг

После деплоя основной риск смещается с пиков сборки на постепенный рост потребления под нагрузкой — типичная картина для любого Node.js-приложения с долгоживущим процессом.

Пул подключений к базе. Каждое открытое соединение к Postgres или MongoDB держит собственный буфер на стороне и клиента, и сервера БД. Для Payload с адаптером db-postgres пул настраивается через pool в конфиге:

// payload.config.ts
import { postgresAdapter } from '@payloadcms/db-postgres'

export default buildConfig({
  db: postgresAdapter({
    pool: {
      connectionString: process.env.DATABASE_URI,
      max: 10, // не завышайте на маленьком сервере
    },
  }),
  // ...
})

Значение max по умолчанию в некоторых конфигурациях выше, чем нужно небольшому проекту — 10 одновременных соединений с запасом хватает для сайта с умеренной посещаемостью админки, а каждое лишнее соединение — это лишние мегабайты на стороне Postgres.

PM2 с автоперезапуском по памяти. Если процесс всё же периодически «пухнет» (утечки в кастомных hooks — не редкость), не гоняйтесь за идеальным исправлением бага прямо сейчас, а поставьте защитный порог:

pm2 start npm --name payload -- run start
pm2 set pm2:max_memory_restart 1200M

Это не решение проблемы утечки, а страховка: процесс перезапустится сам при превышении лимита, вместо того чтобы уронить сервер целиком через OOM killer, который может задеть и соседние сервисы.

Мониторинг. Минимальный набор — free -h раз в день на первую неделю после запуска и алерт по свободной памяти ниже 15%. Если держите на сервере что-то ещё — сравните подход в статье сколько RAM нужно для WordPress, если рассматриваете альтернативные CMS для того же проекта, или посмотрите на сравнение с Strapi, если ещё выбираете между headless-решениями.

Локализация и blocks: скрытые множители памяти

Две особенности Payload, которые редко закладывают в расчёт заранее — локализация (localization в конфиге) и blocks-поля (flexible content, layout builder).

Локализация не дублирует Node.js-процесс, но увеличивает объём каждого документа, который проходит через валидацию и hooks: если у вас 5 локалей и richText-поле переведено на все, in-memory представление документа при сохранении и рендере админки будет в несколько раз тяжелее, чем в одноязычном проекте. На практике это не всегда заметно на CPU, но ощутимо на пиках heap при массовом импорте контента через скрипты — если делаете миграцию тысяч документов, запускайте её порциями, а не одним batch-скриптом на весь датасет.

Blocks-поля (вложенные блоки контента, аналог ACF Flexible Content в WordPress) увеличивают вес схемы, которую Payload держит в памяти для генерации TypeScript-типов и валидации на каждый запрос сохранения. Проект с 20+ типами блоков, вложенными друг в друга на 2-3 уровня, ощутимо тяжелее по памяти схемы, чем проект с плоской структурой из тех же 20 полей — разница обычно в десятках, а не в сотнях мегабайт, но на границе тарифа 2 ГБ это может стать решающим фактором.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Хватит ли 1 ГБ RAM для Payload CMS?

Для рантайма уже собранного standalone-приложения с SQLite и без нагрузки — теоретически да, но без запаса на сборку, swap и рост базы. Для боевого проекта это рискованная конфигурация; 2 ГБ — более реалистичный минимум.

Payload CMS требует больше памяти, чем WordPress?

Node.js-процесс сам по себе обычно легче, чем связка PHP-FPM + MySQL под нагрузкой, но сборка через Next.js (next build) — заметно тяжелее разовой операции, чем что-либо в стандартном WordPress. Для голого рантайма Payload часто экономичнее, для деплоя — наоборот.

Можно ли собирать Next.js/Payload на том же сервере, где крутится продакшн?

Можно, но закладывайте отдельный буфер под пик сборки или переносите сборку в CI — это снимает риск падения продакшн-процесса из-за параллельной пересборки.

MongoDB или PostgreSQL — что экономичнее по RAM?

PostgreSQL в простое обычно легче MongoDB на 100-200 МБ, но разница нивелируется при росте базы и настройке shared_buffers/WiredTiger cache под нагрузку — выбирайте адаптер по архитектуре проекта, а не только по памяти.

Как понять, что серверу не хватает RAM именно из-за Payload, а не БД?

Смотрите htop во время сборки и во время обычной работы отдельно — если пик приходится строго на момент next build или загрузки изображения, дело в рантайме/sharp; если память растёт постоянно и коррелирует с размером таблиц — смотрите в сторону БД и её кеша.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →