Сколько RAM нужно для Invoice Ninja
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 ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →