Сколько RAM нужно для Dify
В документации Dify стоит одна цифра — 2 vCPU и 4 ГБ RAM, — и она сбивает с толку: на четырёх гигабайтах стек поднимается, но живёт до первой серьёзной базы знаний. Память тратит не «Dify», а десяток контейнеров с разными аппетитами, и без потолка растёт из них только один. Ниже — разбор по компонентам, расчёт векторного индекса, замер на своей машине и переменные .env, которые снимают гигабайт.
Содержание
- Короткий ответ: сколько памяти закладывать
- Куда уходят гигабайты: разбор по контейнерам
- Как измерить свой расход, а не поверить чужой таблице
- Векторный индекс: единственная строка, которая растёт без потолка
- Пики: индексация, воркеры и плагины
- Как ужать Dify: .env, лимиты и swap
- Какой сервер под Dify брать в MAATRIX
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Короткий ответ: сколько памяти закладывать
Требования к Dify определяет не число пользователей, а объём базы знаний и количество плагинов. Диалоги — самая дешёвая часть системы: их считает внешняя модель, Dify только перекладывает байты.
| Сценарий | RAM | vCPU | Что ломается ступенью ниже |
|---|---|---|---|
| 1–2 приложения на облачном API, база знаний до сотни документов | 4 ГБ | 2 | на 2 ГБ контейнеры стартуют, но первая индексация убивает worker |
| Отдел 10–30 человек, база в несколько тысяч фрагментов, 3–5 плагинов | 8 ГБ | 4 | на 4 ГБ индексация конкурирует с диалогами и выигрывает |
| База в сотни тысяч фрагментов, гибридный поиск, несколько воркеров | 16 ГБ | 4–8 | на 8 ГБ векторное хранилище занимает половину машины |
| Локальная модель на той же машине: эмбеддинги или 7–8B в Q4 | 16–32 ГБ | 8+ | на 8 ГБ стек и модель не уживаются |
Главное: сам Dify — около двух гигабайт в покое, и эта величина почти не меняется. Всё, что сверху, — векторный индекс, пики индексации и плагины. И поправка, экономящая деньги: Dify не грузит PyTorch и не считает эмбеддинги сам — ни sentence-transformers, ни локального реранкера в контейнерах нет, векторизацию выполняет подключённый плагином провайдер.
Куда уходят гигабайты: разбор по контейнерам
Комплектный docker-compose.yaml поднимает девять-десять сервисов, и «Dify съел всю память» почти всегда значит, что съел один конкретный. Порядок величин в покое:
| Контейнер | Что это | Порядок резидента | От чего растёт |
|---|---|---|---|
api | Flask под gunicorn с воркерами gevent | 450–700 МБ | SERVER_WORKER_AMOUNT |
worker | тот же образ в режиме Celery | 400–900 МБ | индексация, CELERY_WORKER_AMOUNT |
web | Next.js под PM2 | 250–400 МБ | PM2_INSTANCES, по умолчанию 2 |
db | PostgreSQL 15-alpine | 150–400 МБ | POSTGRES_SHARED_BUFFERS, число соединений |
weaviate | векторное хранилище по умолчанию | от 200 МБ и без потолка | размер базы знаний |
plugin_daemon | демон плюс процесс на каждый плагин | 120 МБ + 60–150 МБ за плагин | число плагинов |
redis | брокер Celery и кэш | 10–60 МБ | длина очереди задач |
sandbox | Go-песочница для узла Code | 20–60 МБ | параллельные запуски кода |
ssrf_proxy | Squid для узлов HTTP Request | 40–120 МБ | cache_mem в конфиге Squid |
nginx | единственный публичный порт | 5–20 МБ | практически не растёт |
Цифры — порядок, а не эталон: версия и набор плагинов двигают их процентов на двадцать. Три вещи из таблицы обычно удивляют.
apiиworker— два экземпляра одного приложения. Оба грузят Flask, SQLAlchemy, Celery, SDK провайдеров и парсеры документов, и платить приходится дважды: без воркера не работает индексация.- Демон плагинов множится. В ветке 1.x провайдеры и инструменты вынесены в плагины, и
plugin_daemonзапускает каждый отдельным процессом со своим venv в/app/storage/cwd. Семь плагинов — семь процессов по сотне мегабайт и гигабайты окружений на диске. webзапускается дважды.PM2_INSTANCESравна 2: Next.js держит два процесса Node. Для пары десятков пользователей второй не нужен, а стоит 150–200 МБ.
Развернуть за пару минут
Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть DifyКак измерить свой расход, а не поверить чужой таблице
Dify ставится в подкаталог docker, поэтому имя проекта Compose — docker, а контейнеры зовутся docker-api-1, docker-worker-1.
cd ~/dify/docker
docker compose ps --format 'table {{.Service}}\t{{.Status}}'
docker stats --no-stream --format 'table {{.Name}}\t{{.MemUsage}}\t{{.MemPerc}}'
Вывод второй команды — форма, а не эталон, цифры у вас будут свои:
NAME MEM USAGE / LIMIT MEM %
docker-api-1 612MiB / 3.822GiB 15.64%
docker-worker-1 548MiB / 3.822GiB 14.00%
docker-web-1 318MiB / 3.822GiB 8.13%
docker-weaviate-1 241MiB / 3.822GiB 6.16%
docker-db-1 196MiB / 3.822GiB 5.01%
docker-plugin_daemon-1 173MiB / 3.822GiB 4.42%
docker-ssrf_proxy-1 58MiB / 3.822GiB 1.48%
docker-sandbox-1 21MiB / 3.822GiB 0.54%
docker-redis-1 12MiB / 3.822GiB 0.31%
docker-nginx-1 9MiB / 3.822GiB 0.23%
Ловушка: на cgroup v2 docker stats показывает memory.current вместе со страничным кешем. Настоящую память процесса даёт строка anon, пик — отдельный счётчик ядра:
docker exec docker-worker-1 grep -E '^(anon|file|slab) ' /sys/fs/cgroup/memory.stat
CID=$(docker inspect -f '{{.Id}}' docker-worker-1)
cat /sys/fs/cgroup/system.slice/docker-$CID.scope/memory.peak
memory.peak появился в ядре 5.19 — на Ubuntu 24.04 (ядро 6.8) и Debian 12 он есть; обнуляется записью echo reset, чтобы померить одну операцию. Если стек уже падал, диагноз ставится по всем контейнерам сразу:
docker inspect -f '{{.Name}} OOMKilled={{.State.OOMKilled}} Exit={{.State.ExitCode}}' $(docker compose ps -aq)
dmesg -T | grep -i 'killed process'
Exit=137 и OOMKilled=true означают, что процесс убил не баг, а ядро. В логах авария выглядит по-разному. Celery в docker compose logs worker:
[ERROR/MainProcess] Process 'ForkPoolWorker-2' pid:41 exited with 'signal 9 (SIGKILL)'
billiard.exceptions.WorkerLostError: Worker exited prematurely: signal 9 (SIGKILL) Job: 0.
Gunicorn в docker compose logs api — прямым текстом:
[1] [ERROR] Worker (pid:19) was sent SIGKILL! Perhaps out of memory?
Смерть воркера Celery оставляет документ навсегда в статусе обработки, gunicorn — обрывает ответ пользователю. Общие симптомы — в разборе нехватки RAM.
Векторный индекс: единственная строка, которая растёт без потолка
Всё выше — константа. Векторное хранилище — переменная, и считать её надо заранее: переезжать потом дорого. Weaviate из комплекта держит HNSW-граф в оперативной памяти, и объём считается как «число фрагментов × размерность вектора × 4 байта» (float32) плюс 15–25 % на граф связей.
| Фрагментов в базе | 1024 измерения | 1536 измерений | 3072 измерения |
|---|---|---|---|
| 10 000 | ~40 МБ | ~60 МБ | ~120 МБ |
| 100 000 | ~400 МБ | ~600 МБ | ~1,2 ГБ |
| 500 000 | ~2 ГБ | ~3 ГБ | ~6 ГБ |
| 1 000 000 | ~4 ГБ | ~6 ГБ | ~12 ГБ |
Размерность задаёт модель эмбеддингов: у text-embedding-3-small это 1536, у text-embedding-3-large — 3072, у bge-m3 — 1024. «Большая» модель удваивает расход памяти, качество поиска по документации — обычно нет.
В автоматическом режиме Dify режет документ по абзацам с целевой длиной порядка пятисот токенов; в пользовательском предел держит INDEXING_MAX_SEGMENTATION_TOKENS_LENGTH (по умолчанию 1000). Плотная страница A4 — 500–700 токенов, то есть фрагмент на страницу: сто тысяч фрагментов — порядка восьмидесяти тысяч страниц. Типичная корпоративная база — тысячи, максимум десятки тысяч фрагментов, то есть сотни мегабайт.
Два способа не платить за это памятью — и множитель, о котором забывают:
- Режим индексации «Экономичный» предлагается при создании базы знаний рядом с «Высоким качеством». Он не вызывает модель эмбеддингов вообще: строит инвертированный индекс по ключевым словам и векторное хранилище не занимает. Минус такой же полный: это поиск по словам, а не по смыслу — «как оформить отпуск» не найдёт «ежегодный отдых».
- Другое хранилище.
VECTOR_STOREпереключает бэкенд:qdrantдержит векторы на диске в mmap,pgvectorукладывает всё в тот же Postgres. Оба меняют память на задержку поиска. Важно: сменаVECTOR_STOREне переносит данные — старые базы придётся переиндексировать целиком, заново оплатив эмбеддинги. Решать надо до заливки документов. - Множитель сверху — режим «родительский-дочерний»: он хранит и мелкие фрагменты, и крупные родительские, записей втрое-впятеро больше.
Пики: индексация, воркеры и плагины
Ровное потребление серверы не убивает — убивают пики. У Dify их четыре.
Индексация документов — самый прожорливый момент системы. Воркер читает файл в память целиком, режет на фрагменты, батчами шлёт их модели эмбеддингов и пишет результат в Postgres и векторную базу сразу. Пачка из полусотни документов на четырёх гигабайтах — верный способ получить Exit=137 у worker. Ограничители на входе: UPLOAD_FILE_SIZE_LIMIT (15 МБ) и UPLOAD_FILE_BATCH_LIMIT (5 файлов за раз). За ними стоит ещё NGINX_CLIENT_MAX_BODY_SIZE, иначе вместо ошибки памяти вы получите 413.
ETL_TYPE=Unstructured — движок разбора, который включают ради сложных PDF и таблиц. Он поднимает отдельный контейнер: плюс гигабайт-полтора к постоянному расходу.
Воркеры. Рядом с SERVER_WORKER_AMOUNT в .env.example стоит комментарий про формулу «2 × число ядер + 1». Для лёгких приложений она верна, здесь разрушительна: каждый воркер gunicorn — полная копия приложения на 400–600 МБ, а класс gevent асинхронный, один процесс держит сотни соединений. То же с CELERY_WORKER_AMOUNT.
Плагины висят постоянно, а не поднимаются по запросу. Здесь же отложенная мина: PLUGIN_PYTHON_ENV_INIT_TIMEOUT (120 секунд) — время на создание venv при установке. На забитой памятью машине плагин не «ставится медленно», а падает по таймауту — в интерфейсе это выглядит как «плагин не устанавливается».
Значения Postgres в .env рассчитаны на машину побольше. POSTGRES_EFFECTIVE_CACHE_SIZE=4096MB памяти не выделяет, но на сервере с 4 ГБ даёт планировщику неверную подсказку, а POSTGRES_MAX_CONNECTIONS=100 с POSTGRES_WORK_MEM=4MB — это потенциальные 400 МБ.
Как ужать Dify: .env, лимиты и swap
Сначала правки в docker/.env, которые ничего не ломают:
PM2_INSTANCES=1
SERVER_WORKER_AMOUNT=1
CELERY_WORKER_AMOUNT=1
CELERY_AUTO_SCALE=false
POSTGRES_MAX_CONNECTIONS=60
POSTGRES_SHARED_BUFFERS=192MB
POSTGRES_WORK_MEM=4MB
POSTGRES_MAINTENANCE_WORK_MEM=128MB
POSTGRES_EFFECTIVE_CACHE_SIZE=2048MB
UPLOAD_FILE_BATCH_LIMIT=3
ETL_TYPE=dify
PM2_INSTANCES=1 — самая безболезненная экономия: 150–200 МБ за строку. Дальше удалите неиспользуемые плагины. Переменные перечитываются только при пересоздании контейнеров: docker compose restart оставит старое окружение, и покажется, что правка не сработала.
cd ~/dify/docker && docker compose down && docker compose up -d
Второй слой — ограничители. Файл docker-compose.override.yaml рядом с основным подхватывается автоматически, а git pull его не трогает — в репозитории его нет:
services:
weaviate:
environment:
GOMEMLIMIT: 1GiB
mem_limit: 1400m
worker:
mem_limit: 1500m
api:
mem_limit: 1200m
GOMEMLIMIT — мягкий предел для сборщика мусора Go: Weaviate собирает мусор агрессивнее, а не растёт до упора. mem_limit — предохранитель, и о нём надо честно: он не уменьшает потребление, он локализует смерть. Без лимитов ядро выбирает жертву по oom_score и способно убить Postgres или sshd вместо воркера.
Третий слой — swap: на четырёх гигабайтах это не опция, а обязательный элемент:
fallocate -l 4G /swapfile && chmod 600 /swapfile && mkswap /swapfile && swapon /swapfile
echo '/swapfile none swap sw 0 0' >> /etc/fstab
sysctl -w vm.swappiness=10
Десятка вместо дефолтных 60 значит, что ядро полезет в swap, только когда припёрло. Swap гасит пик индексации, но если туда уезжает Weaviate или Postgres, поиск по базе из миллисекунд превращается в секунды. Чего делать не стоит: отключать sandbox и ssrf_proxy ради полутора сотен мегабайт — первый изолирует выполнение кода из workflow, второй не пускает узел HTTP Request во внутреннюю сеть и в метаданные облака.
Какой сервер под Dify брать в MAATRIX
Конфигурация выводится из двух чисел: базового расхода стека (около 2 ГБ) и размера индекса по формуле из четвёртого раздела. Остальное — запас на пики.
Честный минимум: 2 vCPU, 4 ГБ RAM, 40–50 ГБ NVMe. Ровно документационный порог: консоль работает, два-три приложения на облачных моделях отвечают нормально, база в сотни документов индексируется. Ограничения называю прямо: swap обязателен, PM2_INSTANCES=1 обязателен, ETL_TYPE=Unstructured недоступен, плагинов — минимум, документы заливать порциями. Конфигурация для пилота, а не для растущей базы.
Комфортный вариант: 4 vCPU, 8 ГБ RAM, 80–100 ГБ NVMe. Считать мегабайты уже не нужно: два гигабайта стека, до гигабайта индекса, полдесятка плагинов, пик индексации — и всё ещё свободная память. Если база планируется на сотни тысяч фрагментов или нужен гибридный поиск с реранкером — сразу 16 ГБ. Диск считайте кратно объёму документов: образы, оригиналы в storage, Postgres, индекс, venv плагинов и логи. Двадцати гигабайт мало даже на старте.
Локация — Великобритания, Лондон. К памяти это отношения не имеет, но определяет, будет ли Dify работать вообще: с российского адреса маркетплейс плагинов не открывается, а OpenAI, Anthropic и Google отвечают отказом по региону — провайдер смотрит на исходящий IP, перевыпуск ключа не помогает. Лондон снимает обе проблемы и ближе к пользователям в Европе и России, чем Нью-Йорк. США берут ради американского IP, Франция — равноценная альтернатива, Россия оправдана только под 152-ФЗ с российскими моделями.
Dify есть в каталоге apps.maatrix.io и разворачивается автоматически при заказе сервера — вручную ставить Docker и разбираться с compose-файлом не нужно. Работает на Ubuntu и Debian. Адрес консоли и стартовые доступы появятся в личном кабинете, в разделе «Доступ». Оплата — картой российского банка, по СБП, криптовалютой или токеном MAAT: иностранная карта не нужна, хотя сервер стоит в Лондоне. Пошаговая настройка — в установке Dify на VPS, разбор аварий — в частых ошибках Dify, сравнение — в Dify против Flowise.
Развернуть за пару минут
Готовый образ на VPS MAATRIX: NVMe, AMD EPYC, root-доступ. Локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Развернуть DifyОбсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Частые вопросы
Хватит ли 2 ГБ RAM для Dify?
Нет. Стек стартует и первые полчаса выглядит рабочим, но базовое потребление около двух гигабайт — на них уже нет места ни системе, ни Docker. Первая загрузка документа даёт Exit=137 у контейнера worker и WorkerLostError: Worker exited prematurely: signal 9 (SIGKILL) в логах.
Weaviate занимает три гигабайта и не отдаёт память после удаления базы знаний. Это утечка?
Обычно нет: удалённые объекты помечаются надгробиями и вычищаются из HNSW-графа асинхронно, а память, освобождённую сборщиком Go, процесс не всегда сразу возвращает системе. Если через сутки цифра не изменилась, помогает docker compose restart weaviate.
Поднял SERVER_WORKER_AMOUNT до 9 по формуле «2 × CPU + 1», и сервер стал падать. Почему?
Каждый воркер gunicorn — полная копия приложения на 400–600 МБ, девять копий это 4–5 ГБ только под api. Формула написана для синхронных воркеров, а Dify использует gevent. Начинайте с 1 и поднимайте до 2–3, только когда упирается процессор, а не память.
Нужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.