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

Сколько RAM нужно для Excalidraw

MAATRIX

Excalidraw — удобная доска для набросков схем «от руки», и многие команды хотят собственный инстанс вместо публичного excalidraw.com: без чужого домена в адресной строке и без риска, что бесплатный сервис однажды поменяет правила. Проблема в том, что документация проекта почти ничего не говорит про сайзинг сервера — просто «разверните через Docker». На деле self-hosted Excalidraw — это не одно приложение, а минимум два разных процесса с очень разной нагрузкой на память, и путать их — типичная причина, почему сервер либо простаивает впустую, либо неожиданно тормозит при совместном редактировании. Разберём по частям.

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

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

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

Как устроен self-hosted Excalidraw изнутри

Ключевая вещь, которую нужно понять перед выбором тарифа: Excalidraw — это не монолит, а связка из независимых кусков, и каждый ест память по-своему.

  • Фронтенд (excalidraw/excalidraw) — это статическая сборка React-приложения. Вся логика рисования, слоёв, экспорта в PNG/SVG выполняется в браузере пользователя. На сервере от неё нужен только веб-сервер, который отдаёт статику: nginx-контейнер из официального образа или любой другой раздатчик файлов. Сама по себе эта часть почти не потребляет RAM — она не выполняет вычислений, только отдаёт HTML/JS/CSS.
  • Room-сервер (excalidraw/excalidraw-room) — отдельный Node.js-процесс на socket.io, который отвечает за совместное редактирование в реальном времени. Именно он держит WebSocket-соединения между участниками одной доски и ретранслирует изменения элементов между клиентами. Это единственная часть, которая реально «живёт» на сервере как процесс с состоянием (открытые соединения, список активных комнат).
  • Хранилище (опционально) — сам Excalidraw по умолчанию не хранит доски на сервере постоянно: обмен идёт «на лету» через room-сервер, а данные шифруются на стороне клиента (сервер видит только зашифрованные байты, ключ шифрования — часть ссылки на комнату, после #). Если нужно сохранять доски между сессиями, поверх обычно добавляют собственное хранилище — например, S3-совместимое (MinIO) для экспортированных сцен и картинок. Это не входит в официальный docker-образ и добавляется вручную.

Отсюда и главный практический вывод: если вам нужна доска «для себя, без совместной работы в реальном времени», хватит одного статического фронтенда — это копейки по ресурсам. Если нужна именно совместная работа нескольких человек одновременно — считать RAM нужно уже для room-сервера, и вот там цифры зависят от нагрузки, а не фиксированы.

Сколько RAM нужно по факту: ориентиры

Официальных бенчмарков от команды Excalidraw по потреблению памяти room-сервера нет — проект не публикует цифры сайзинга, потому что нагрузка сильно зависит от числа одновременных досок и объёма данных, которые через них гоняют (в первую очередь — вложенные изображения). Ниже — ориентировочные пороги, собранные из практики эксплуатации похожих Node.js/socket.io-сервисов ретрансляции; на вашей нагрузке цифры могут отличаться, особенно если пользователи активно вставляют скриншоты и фотографии в доски.

СценарийАктивных комнат одновременноRAMvCPUДиск
Только просмотр/рисование соло, без live-коллаборации— (нужен лишь статик)256–512 МБ15–10 ГБ
Небольшая команда, совместное редактирование1–10 комнат, 2–5 участников в каждой512 МБ–1 ГБ110–20 ГБ
Активное использование в компании10–50 комнат одновременно1–2 ГБ1–220–40 ГБ
Много параллельных сессий + собственное хранилище сцен/картинок50+ комнат, S3-хранилище2–4 ГБ2–440–100 ГБ+

Важная оговорка: сам процесс excalidraw-room в простое ест обычно в районе 60–120 МБ — это лёгкий Node.js-сервис без базы данных внутри. Основной расход памяти на пике — не «база пользователей», а объём данных, который проходит через ретрансляцию: чем больше элементов на доске (особенно вставленных изображений в base64) и чем больше участников синхронизируется одновременно, тем выше кратковременные скачки потребления. Если взять минимальный тариф впритык под тихий режим, сервис не упадёт в обычный день, но может захлебнуться именно в момент общей сессии брейншторма, когда десяток человек одновременно рисуют и вставляют скриншоты — а это худший момент для деградации.

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

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

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

Что реально нагружает память

Если хочется понимать причину расхода, а не просто верить таблице — вот конкретные источники:

  • Число одновременных WebSocket-соединений. Каждый подключённый клиент в комнате — это открытый сокет на стороне room-сервера. Сама по себе одна связь лёгкая, но при десятках участников в разных досках одновременно накладные расходы socket.io начинают быть заметны.
  • Ретрансляция изменений сцены. При каждом движении курсора, добавлении фигуры или тексте сервер пересылает событие всем участникам комнаты. Событий много, но каждое маленькое — это скорее нагрузка на CPU и сеть, чем на RAM, если только доска не огромная.
  • Вставленные изображения. Это главный «тяжёлый» кейс. Excalidraw хранит вставленные картинки как файлы, привязанные к элементам сцены, и при синхронизации новый участник получает всю историю файлов доски. Доска с десятком вставленных скриншотов на пару мегабайт каждый — это заметный кратковременный расход памяти при подключении нового клиента или при полной пересылке состояния.
  • Количество параллельных активных комнат. Room-сервер держит состояние (список подключений и минимальные метаданные) на каждую активную комнату. Одна комната — не проблема, полсотни активных одновременно на общем сервере — уже нагрузка, которую стоит закладывать в расчёт.
  • Reverse proxy и TLS-терминация. Если, как обычно рекомендуется, ставить всё за nginx или Caddy — это ещё 20–50 МБ поверх самих контейнеров, плюс отдельная настройка для проксирования WebSocket (об этом ниже).

Установка в Docker: фронтенд + сервер комнат

Для полноценной совместной работы нужны два контейнера — статический фронтенд и room-сервер для realtime-синхронизации. Пример docker-compose.yml с явными лимитами памяти:

services:
  excalidraw:
    image: excalidraw/excalidraw:latest
    container_name: excalidraw-app
    restart: unless-stopped
    ports:
      - "127.0.0.1:5000:80"
    deploy:
      resources:
        limits:
          memory: 256m
        reservations:
          memory: 64m

  excalidraw-room:
    image: excalidraw/excalidraw-room:latest
    container_name: excalidraw-room
    restart: unless-stopped
    ports:
      - "127.0.0.1:3002:80"
    environment:
      - PORT=80
    deploy:
      resources:
        limits:
          memory: 512m
        reservations:
          memory: 128m

Оба порта намеренно привязаны к 127.0.0.1 — наружу всё отдаётся через reverse proxy с TLS, а не напрямую. Фронтенду нужно знать адрес room-сервера: при сборке своего образа или через переменную окружения VITE_APP_WS_SERVER_URL (в зависимости от версии сборки) указывается публичный URL комнаты — обычно wss://ваш-домен/socket.io через тот же reverse proxy, чтобы не открывать отдельный поддомен и не городить лишние DNS-записи.

Лимит memory: 512m для room-сервера в примере — это защита от аномалий (утечка после долгого аптайма, зависшая комната с забытыми подключениями), а не рекомендуемый минимум для всего сервера в целом: с учётом ОС, nginx, бэкапов и возможного хранилища картинок реальный сервер должен иметь запас сверху.

Nginx как reverse proxy для WebSocket-соединений

Главная особенность Excalidraw по сравнению с обычным сайтом — комната работает через WebSocket, а не просто HTTP-запросы, поэтому reverse proxy нужно настроить с явным проксированием upgrade-заголовков, иначе совместное редактирование просто не подключится (доска откроется, но синхронизация с другими участниками не заработает). Минимальный конфиг для связки на одном домене:

server {
    listen 443 ssl;
    server_name board.example.com;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
    }

    location /socket.io/ {
        proxy_pass http://127.0.0.1:3002;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 86400;
    }
}

Заголовки Upgrade и Connection "upgrade" обязательны — без них nginx держит соединение как обычный HTTP-запрос, и WebSocket-хендшейк не пройдёт. proxy_read_timeout 86400 увеличен специально: долгая сессия совместного рисования — это открытое соединение на часы, и стандартный таймаут в 60 секунд просто разорвёт синхронизацию у тех, кто сейчас не рисует, но продолжает смотреть на доску. Пошаговую настройку nginx как reverse proxy с нуля разбирали в отдельной статье.

Как выбрать сервер и масштабировать при росте нагрузки

Для личного использования или небольшой команды без постоянной параллельной работы хватает младшего тарифа VPS — 512 МБ–1 ГБ RAM и 1 vCPU. Важнее не запас по памяти, а стабильный аптайм: если room-сервер падает посреди совместной сессии, все участники теряют live-синхронизацию (сами доски при этом не пропадают у тех, кто уже открыл их локально, но новые изменения перестают доходить друг до друга).

Если у вас активная команда с регулярными сессиями брейншторма на 10+ человек одновременно, закладывайте 2 ГБ RAM и 2 vCPU — резерв нужен не столько под сам room-сервер в среднем состоянии, сколько под пиковую пересылку изображений при подключении новых участников к уже насыщенной доске. При росте числа параллельных комнат за пределы одного процесса возникает классическая для socket.io проблема горизонтального масштабирования: несколько инстансов room-сервера за балансировщиком нужно объединять через Redis-адаптер, иначе участники одной комнаты, попавшие на разные инстансы, просто не увидят изменения друг друга. До этого доходит редко — обычно один room-сервер на 1–2 ГБ RAM вытягивает десятки одновременных комнат без проблем, но для сервиса на сотни сотрудников такую архитектуру стоит закладывать заранее.

Если параллельно с Excalidraw на том же сервере крутится что-то ещё из инструментов совместной работы — например, Focalboard для канбан-досок или Collabora Online для совместного редактирования документов, — считайте память под каждый сервис отдельно и суммируйте, а заодно явно выставьте лимиты памяти на контейнеры, чтобы один раздувшийся процесс не утащил за собой остальные сервисы на общем хосте.

Для локации принципиальных требований нет — Excalidraw не критичен к задержке в духе видеозвонка: события ретранслируются асинхронно, и 80–150 мс до сервера почти не ощущаются как лаг при рисовании. Выбирайте локацию по цене и удобству оплаты; из России это чаще всего означает сервер с оплатой картой или криптовалютой напрямую, без конвертации через посредников.

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

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

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

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

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

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

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

Для одиночного использования без live-коллаборации — с запасом. Для совместной работы небольшой командой (до 5–10 человек в разных комнатах) — тоже хватит, но без большого запаса на пики со вставкой картинок.

Нужен ли room-сервер, если я просто хочу личную доску для себя?

Нет. Без совместного редактирования в реальном времени достаточно только статического фронтенда — room-сервер нужен именно для синхронизации между несколькими участниками одной комнаты.

Хранит ли Excalidraw доски на сервере постоянно?

Из коробки — нет, обмен идёт через ретрансляцию, данные зашифрованы на клиенте. Для постоянного сохранения досок между сессиями нужно добавлять собственное хранилище (например, S3-совместимое) — это делается отдельно от официального docker-образа.

Растёт ли нагрузка линейно с числом пользователей?

Нет, она сильнее зависит от числа одновременно активных комнат и объёма вставленных изображений, чем от общего числа зарегистрированных пользователей — большинство из которых в моменте просто не подключены.

Можно ли развернуть Excalidraw без Docker?

Можно, оба компонента — обычные Node.js/статические приложения, но Docker сильно упрощает обновления и позволяет явно ограничивать память на каждый сервис отдельно, что для realtime-сервиса важнее, чем кажется на старте.

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

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

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