MAATRIX / Блог / Сколько RAM нужно для Invoice Ninja

Сколько RAM нужно для Invoice Ninja

MAATRIX

Invoice Ninja выглядит как лёгкое веб-приложение для выставления счетов, и по интерфейсу это ощущение не обманывает — страницы открываются быстро, форм немного. Но именно эта категория self-hosted сервисов регулярно подводит тех, кто считает память «на глаз»: рядом с самим PHP-приложением почти всегда живут база данных, очередь фоновых задач и headless-браузер для генерации PDF, а последний компонент по аппетиту сравним с полноценным Chrome. Разберём, из чего реально складывается расход памяти у Invoice Ninja, почему рендер счёта в PDF — самый частый повод для OOM на слабом тарифе, и какой сервер брать под фрилансера, небольшую компанию и агентство с десятками клиентов.

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

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

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

Из чего состоит Invoice Ninja и что реально ест память

Invoice Ninja пятой версии (текущая стабильная ветка) — это приложение на Laravel с фронтендом на Vue/React, которое официально разворачивается Docker Compose из нескольких контейнеров:

  • PHP-FPM (app) — обрабатывает запросы веб-интерфейса и API: список счетов, клиенты, отчёты, платежи. Каждый воркер держит в памяти загруженный Laravel-контейнер, но нагрузка от одного-двух пользователей в моменте невелика.
  • MySQL/MariaDB — хранит клиентов, счета, платежи, шаблоны, продукты. Invoice Ninja официально ориентирован на MySQL/MariaDB как основную СУБД; PostgreSQL поддерживается, но менее протестирован сообществом, и в официальных образах по умолчанию используется MySQL-совместимая база.
  • Redis — не строго обязателен, но настоятельно рекомендуется для очереди фоновых задач и кеша сессий. Без него часть операций (отправка писем, генерация PDF) выполняется синхронно прямо в запросе пользователя, что не столько экономит память, сколько превращает нагрузку из фоновой в пиковую именно в момент клика «Отправить счёт».
  • Queue worker (php artisan queue:work) — отдельный долгоживущий PHP-процесс, который разбирает очередь: отправка email, генерация PDF, повторяющиеся счета. В отличие от PHP-FPM воркеров, которые умирают между запросами, это постоянно работающий процесс — стабильная, а не всплесковая статья расхода.
  • Cron — раз в минуту вызывается php artisan schedule:run для повторяющихся счетов, автонапоминаний о просрочке и курсов валют. Короткий процесс, но поднимает полноценный PHP-контекст поверх уже работающих компонентов.

Отдельно и заметнее всего стоит генерация PDF. Invoice Ninja рендерит счета и сметы через headless Chromium (пакет snappdf с закешированным бинарником браузера) — это тот же класс нагрузки, что у любого сервиса, который «фотографирует» HTML-страницу через безголовый браузер, а не через лёгкую библиотеку вроде wkhtmltopdf. Каждый запуск рендера — это временный процесс Chromium с собственным потреблением памяти поверх PHP и базы.

Короткий ответ: сколько закладывать

Ориентир для официальной Docker-связки (app + MySQL + Redis) на Ubuntu 24.04, Invoice Ninja v5 последней стабильной сборки на конец лета 2026 года. Это практический диапазон, а не измеренный бенчмарк — конкретные цифры у вас сдвинутся в зависимости от частоты генерации PDF и числа одновременных пользователей.

RAMЧто реально помещаетсяЧестный комментарий
512 МБТест-инсталляция, один пользовательРендер PDF под нагрузкой — риск OOM, не для продакшена
1 ГБФрилансер, 1-2 пользователя, несколько счетов в деньРабочий минимум, если Redis и очередь настроены
2 ГБМалый бизнес, 3-5 пользователей, регулярные PDF и email-рассылкиКомфортно, с запасом на пиковый рендер счетов
4 ГБАгентство или бухгалтерия на аутсорсе, десятки клиентов, много компаний в одной инсталляцииПараллельная генерация нескольких PDF без деградации
8 ГБТо же плюс соседние сервисы на одном сервереНе сам Invoice Ninja требует столько, а совместное размещение

Число «пользователей» здесь условно — важнее интенсивность операций, которые запускают Chromium: массовая рассылка счетов в начале месяца или экспорт отчётов создаёт кратковременный пик, который и определяет нижнюю границу тарифа, а не фоновое присутствие сервиса в простое.

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

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

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

Почему официальный минимум обманчив

В документации Invoice Ninja для ручной установки минимальные требования к PHP-окружению скромные — формально сервис стартует и на 512 МБ, если база данных вынесена на отдельный хост или используется совсем небольшой объём данных. Но это описывает запуск кода, а не типичную инсталляцию «всё на одном VPS», где рядом крутятся MySQL, Redis, queue worker и по требованию — Chromium для PDF.

Проблема усугубляется тем, что Chromium под snappdf — не всегда демон в фоне, а процесс, который поднимается на время рендера и в этот момент претендует на десятки-сотни мегабайт сверх базового потребления. На тарифе 512 МБ-1 ГБ без свопа это часто выглядит так в dmesg -T | tail:

chrome invoked oom-killer: gfp_mask=0x140cca, order=0, oom_score_adj=0
Out of memory: Killed process 2210 (chrome) total-vm:892440kB,
anon-rss:210120kB, file-rss:0kB, shmem-rss:0kB, UID:1000 oom_score_adj:0

Типичный симптом — счёт «зависает» в статусе черновика или письмо клиенту не уходит с вложением, при этом в интерфейсе Invoice Ninja ошибки может и не быть: процесс убит снаружи ядром, а не изнутри приложения, и в логах Laravel (storage/logs/laravel.log) остаётся лишь оборванная задача очереди.

Без Redis картина не лучше, а хуже. Если очередь не настроена и стоит QUEUE_CONNECTION=sync, генерация PDF и отправка письма выполняются синхронно в том же PHP-FPM воркере, который обслуживает запрос пользователя — то есть пик памяти от Chromium накладывается прямо на веб-запрос, а не выносится в фоновый процесс с предсказуемым временем выполнения.

Как замерить память своей установки

PSS вместо RSS. В Docker-инсталляции контейнеры видно по отдельности:

docker stats --no-stream --format "table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}"
NAME                 MEM USAGE / LIMIT     MEM %
invoiceninja_app     240MiB / 1.909GiB      12.57%
invoiceninja_db      190MiB / 1.909GiB       9.94%
invoiceninja_cache   35MiB / 1.909GiB        1.83%

Это снимок в простое. Запустите генерацию нескольких PDF подряд (массовая рассылка счетов или пакетный экспорт) и повторите команду — разница между покоем и пиком у контейнера app, внутри которого и живёт Chromium, обычно самая заметная во всей связке.

Отдельно проверьте память Chromium-процесса. Если приложение установлено вручную, а не через официальный Docker-образ, полезно посмотреть на дочерние процессы PHP-FPM в момент рендера:

ps aux --sort=-%mem | grep -E 'chrome|snappdf' | head -5

available, а не free. На сервере, который живёт не первый день, интерпретация free -m стандартная для Linux:

               total        used        free      shared  buff/cache   available
Mem:            1968         740         96         42        1132        1050
Swap:           2047           0        2047

Занято 740 МБ, свободного всего 96, но реально доступно 1050 — это колонка available. Тревожный признак не низкий free, а available ниже 15% от total вместе с ростом Swap used день за днём, а не разово во время рассылки счетов в конце месяца.

Что реально удваивает потребление

У Invoice Ninja список факторов, которые заметно двигают требования к памяти, короче, чем у CMS или CRM, но каждый пункт весом.

Что включаете/делаетеПриблизительный эффектКомментарий
Генерация PDF через snappdf/Chromium+100-250 МБ на время рендераГлавный источник пиков, а не фоновая нагрузка
Массовая рассылка счетов (десятки/сотни за раз)Пики складываются, если нет ограничения параллелизма очередиНастройте queue:work --max-jobs и число воркеров разумно
Несколько компаний в одной инсталляции (multi-company)Незначительный рост базы, память растёт медленнее данныхДрайвер расхода — не число компаний, а частота операций
Кастомные PDF-дизайны с изображениями/логотипами высокого разрешенияЗаметный, но кратковременный всплеск на рендерОптимизация логотипов клиента снижает пик
API-интеграции (платёжные шлюзы, синхронизация с бухгалтерией)+30-60 МБ на активные вебхуки и очередьРазовые всплески, не постоянная нагрузка
Отключённый Redis (QUEUE_CONNECTION=sync)Переносит пик PDF прямо в веб-запросЭкономии памяти на самом деле нет — риск таймаутов растёт

Практический совет: если рассылаете счета пачками в начале месяца, ограничьте число параллельных воркеров очереди (php artisan queue:work --tries=3 с одним-двумя процессами под supervisor на слабом тарифе) — это растягивает нагрузку по времени вместо одновременного всплеска десятков Chromium-процессов.

Рабочий конфиг под 1-2 ГБ

Расклад для фрилансера или небольшой команды из 2-3 пользователей, MySQL как СУБД, Redis для очереди. Логика для 2 ГБ: 2048 МБ минус система и SSH (150 МБ) минус MySQL (250 МБ) минус Redis (40 МБ) минус запас на Chromium-пик (300 МБ) — остаётся около 1300 МБ на PHP-FPM и очередь с комфортным запасом.

; /etc/php/8.3/fpm/pool.d/invoiceninja.conf
pm = ondemand
pm.max_children = 6
pm.process_idle_timeout = 15s
pm.max_requests = 300
php_admin_value[memory_limit] = 256M

ondemand вместо dynamic — воркеры поднимаются под конкретный запрос и умирают после простоя, что для сервиса с редкими обращениями (проверить статус счетов, выставить новый) экономит память в те часы, когда сервисом никто не пользуется.

Очередь — с ограниченным числом процессов, чтобы Chromium-рендеры не запускались все разом:

[program:invoiceninja-worker]
command=php /var/www/invoiceninja/artisan queue:work --sleep=3 --tries=3 --max-jobs=50
numprocs=2
autostart=true
autorestart=true

База — консервативно:

[mysqld]
innodb_buffer_pool_size = 192M
innodb_log_file_size    = 48M
max_connections         = 30
performance_schema      = OFF

Подробный разбор аналогичных параметров — в статье про оптимизацию MySQL под 1 ГБ RAM, большинство рекомендаций оттуда применимо напрямую. Для установки самого Redis — краткая инструкция в статье про настройку Redis на VPS.

Ещё две вещи, которые окупаются на 1-2 ГБ:

  • Своп на 1-2 ГБ обязателен, а не опционален — пик от Chromium при массовой рассылке счетов именно тот случай, для которого своп и придуман: кратковременная подушка, а не постоянная замена RAM. Проверьте swapon --show, если пусто — добавьте: fallocate -l 2G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile и строку в /etc/fstab. Подробнее — в статье про правильный размер swap для VPS.
  • Ограничьте число одновременных воркеров очереди, а не только PHP-FPM — на слабом тарифе numprocs=2 вместо значения по умолчанию не даёт нескольким Chromium-процессам подняться одновременно и съесть весь запас за секунды.

Если после этих настроек сервис всё равно подтормаживает без явной причины, общий чек-лист разбора — в статье что делать при нехватке RAM.

Какой сервер под Invoice Ninja взять в MAATRIX

Честный минимум: 1 vCPU, 1 ГБ RAM, 20 ГБ NVMe. Для фрилансера или одного-двух пользователей с несколькими счетами в неделю этого достаточно, если Redis настроен и очередь ограничена по числу воркеров. Массовая рассылка десятков счетов разом на этом тарифе — риск, разовый счёт клиенту — нет.

Комфортный вариант: 2 vCPU, 2 ГБ RAM, 40 ГБ NVMe. Подходит малому бизнесу с 3-5 пользователями, регулярными PDF-рассылками и вложениями. Второй гигабайт — это запас именно на пиковый рендер, а не на постоянную фоновую нагрузку, а второе ядро снимает конкуренцию между веб-запросами и очередью в момент массовой отправки счетов.

Агентство или аутсорс-бухгалтерия: 2-4 vCPU, 4 ГБ RAM, 80 ГБ NVMe. Если через одну инсталляцию ведётся учёт для десятков клиентов с несколькими компаниями и параллельной генерацией отчётов, дополнительная память и ядра снимают деградацию при одновременном рендере нескольких PDF.

Локация — по расположению клиентов и банка-эквайера. Invoice Ninja не критичен к сетевой задержке для самого интерфейса, но если платёжный шлюз или бухгалтерская интеграция географически привязаны к региону, логичнее держать сервер там же: для российских клиентов — локация в России, для работы с зарубежными платёжными системами — США или Великобритания, разница в отзывчивости веб-интерфейса при этом малозаметна.

Invoice Ninja из каталога apps.maatrix.io разворачивается на сервер автоматически при заказе — docker-compose поднимать вручную не нужно. Адрес, логин и данные доступа появляются в личном кабинете сразу после установки. Дальше остаётся донастроить число воркеров очереди под свою интенсивность рассылок и, при необходимости, буферный пул базы. Оплата — картами российских банков, по СБП, криптовалютой или токеном MAAT, иностранная карта не требуется даже для локаций в США и Великобритании.

Если сомневаетесь между 1 и 2 ГБ — критерий простой: рассылаете ли счета пачками (закрытие месяца, массовые напоминания о просрочке) или по одному. Пачками — берите 2 ГБ, для единичных операций хватит и минимального тарифа.

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

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

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

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

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

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

Хватит ли 512 МБ RAM для Invoice Ninja?

Формально сервис запускается и там, но это рискованно для продакшена: MySQL, Redis и Chromium для рендера PDF рядом с PHP-FPM почти не оставляют запаса, и первая же рассылка нескольких счетов подряд может привести к тому, что ядро убьёт процесс генерации PDF. Для теста годится, для работы с реальными клиентами — нет.

Обязателен ли Redis для Invoice Ninja?

Формально нет, приложение может работать с синхронной обработкой очереди (QUEUE_CONNECTION=sync), но тогда генерация PDF и отправка письма выполняются прямо в запросе пользователя, а не в фоне — это не экономит память, а переносит пик в момент клика и увеличивает риск таймаута. На продакшене Redis и отдельный queue worker — фактический стандарт, а не опция.

Почему сервер тормозит именно при массовой рассылке счетов?

В этот момент очередь одновременно запускает несколько задач генерации PDF, каждая из которых поднимает отдельный процесс headless Chromium — кратковременный, но заметный пик CPU и памяти, пропорциональный числу задач, обрабатываемых параллельно. Ограничение числа воркеров очереди растягивает нагрузку во времени вместо одновременного всплеска.

Растут ли требования к памяти с числом клиентов и счетов?

Незначительно и постепенно, в основном через размер базы данных, а не через сам PHP-код. Тысячи счетов и клиентов за несколько лет по-прежнему помещаются в 2-4 ГБ RAM; определяющий фактор — не объём накопленных данных, а интенсивность операций рендера PDF и рассылок в моменте.

Можно ли использовать PostgreSQL вместо MySQL, чтобы сэкономить память?

Технически поддержка есть, но официальная документация и большинство продакшен-инсталляций ориентированы на MySQL/MariaDB, и заметной разницы в потреблении памяти между двумя СУБД для типичного объёма данных биллинга нет — выбор скорее вопрос личных предпочтений и совместимости с готовыми Docker-образами.

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

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

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