B2B-клиент попросил «как в Google Docs, только для нашего внутреннего портала». Раньше мы собрали бы кастомное OT-решение. В 2025 - взяли Yjs и закрыли задачу за 6 недель. Делимся архитектурой.
Что такое Yjs (если коротко)
Библиотека CRDT для realtime-коллаборации. Алгоритм сам разрешает конфликты слияния, без сервера-арбитра. Используется в Notion, Linear (частично), внутренних инструментах десятков SaaS-команд.
Архитектура
- Клиент: Yjs + ProseMirror для редактора + y-prosemirror плагин.
- Транспорт: y-websocket поверх Hocuspocus (готовый сервер с auth и persistence).
- Persistence: автосохранение в Postgres каждые 5 секунд (бинарный snapshot документа).
- Awareness: отдельный канал для курсоров и presence - не пишется в БД.
- История: периодические snapshots в S3 для restore.
Что неочевидно
- Yjs-документы со временем растут (история изменений). Нужно делать snapshot + reset раз в N дней, иначе размер растёт линейно.
- Авторизация привязывается к комнате (room), не к отдельным операциям. Если нужны fine-grained права (один пользователь читает, другой пишет) - это отдельная логика на сервере.
- Offline-edit поддерживается, но конфликты при долгом оффлайне (сутки+) могут давать неожиданные слияния. Стоит логировать и алертить.
Цифры
- Время реализации: 6 недель командой из 2 человек.
- Размер фронтенд-bundle: +85 КБ gzipped (Yjs + ProseMirror + плагины).
- Latency на синхронизации: 40–80 мс в одном дата-центре, 150–250 мс между континентами.
- Поддержка одновременных редакторов в одном документе: тестировали до 25, реальный пик у клиента - 12.