Unidraw — путь длиной в два года

Привет! Я Георгий, разработчик команды, которая создавала Unidraw. Расскажу историю о том, как мы искали инструмент для совместных сессий на виртуальной доске. Сначала развернули опенсорсное решение, но потом у нас так выросла нагрузка, что пришлось писать свое. Статья — о том, как начинался продукт, какой он сейчас и каким мы хотим видеть его в будущем. Буду т технические данные, красивые шаблоны и история нашей главной ошибки.
Поиск подходящих решений
Мы постоянно используем сервисы с виртуальными досками, остановились на одном варианте, но с 2022 года искали альтернативу. Для нас важно, чтобы мы могли:
- Проводить ретроспективу
- Делать быстрые наброски мокапов, которым не нужна дизайнерская проработка
- Рисовать архитектурные схемы для обсуждения
- Проводить онлайн-встречи с визуализацией артефактов
- Обучать коллег
Рассматривали разные варианты, в том числе BoardOs, но когда связались с ними, они ответили, что не планируют развитие для России, и локализуют свое приложения только для Китая.
У найденных решений были ограничения по количеству доступов к доскам, или они решали узкоспециализированные задачи.
В это же время пришла помощь от наших архитекторов, которые показали проект Open Source с P2P-шифрованием передачи данных. Мы р ешили на его основе поднять свой сервис-аналог с возможностью делиться ссылками, сохранять результаты в кабинете на сервере и добавлять реципиентов к контенту доски.
Open-source-решение предлагало:
- одну доску максимум;
- поддержку коллективных сессий;
- хранение доски в браузере пользователя.
Технические детали решения:
- socket.io для синхронизации изменений между пользователями;
- нет единого источника правды: все клиенты хранят состояние доски у себя;
- на клиенте есть механизм Reconciliation, который умеет мержить изменения от разных пользователей;
- обновление доски привязано к жизненному циклу React.
Первые шаги нового продукта
Взяв за основу опенсорсный проект, мы создали кабинет, в котором пользователь видит все созданные им доски и проекты, по которым мог распределить эти доски.
В кабинете можно делится досками, давать общий доступ на весь проект с досками с распределением прав на чтение или редактирование — не только одной доски, а сразу всех досок этого проекта.
Задачей номер один было настроить персистентное хранилище досок. Техническое решение принимали в пользу скорости реализации, чтобы обкатать MVP и понять, насколько приложение может быть востребованным, поэтому:
- Доска сохранялась целиком (JSON-объект) в БД каждые 20 секунд.
- Локов при коллективных сессиях не было, каждый клиент выполнял сохранение независимо друг от друга. Небольшая нагрузка от 1 500 пользователей позволяла нам это делать.
- В коллективных сессиях вновь зашедший пользователь получал данные доски не только с БД, но и от других пользователей по сокету. Поэтому в худшем случае данные в БД неактуальны 20 секунд.
Мы запустили сервис в конце сентября 2022 года и не делали никакого внутреннего маркетинга, кроме метода «расскажи другу». В первый же месяц мы получили 250 стабильно использующих сервис пользователей.
Количество пользователей росло органическим способом — ссылки на доски передавали из рук в руки. За это время мы решали задачи по развитию функционала:
- сделали ссылки на место на доске: если после передачи этой ссылки другому пользователю он вставит ее в браузер, доска откроется на том месте, которое указал создатель ссылки;
- добавили фреймы и стикеры;
- добавили Color Picker, расширив возможности цветовой дифференциации элементов на доске;
- добавили snap-объекты — линии, которые позволяют позиционировать элементы относительно друг друга.
На этом этапе мы стали получать сообщения, что система вполне удовлетворяет их потребностям в решении большого количества задач, для которых использовали Miro и другие системы. Например, к нам стали переходить из Storm BPM, draw.io и других.
Приложение постепенно набирало обороты. По MAU к февралю 2023 года мы подошли к значениям, сопоставимым с количеством пользователей, которые использовали Miro на тот момент, когда мы хотели купить их лицензию для компании. А к началу марта перешли порог 2000 MAU.
Возрастающая нагрузка больше не позволяла приложению работать по той схеме, которую выбрали для бэкенда изначально, — хранить полные модели досок одной записью. С такой схемой мы смогли прожить не больше года.
Ко второй итерации мы пришли с новым решением:
- отказались от хранения досок целиком: нужно, чтобы каждый объект на доске сохранялся и передавался отдельно;
- БД стали единственным источником правды;
- изменения каждого объекта записывали сразу, а не раз в 20 секунд, как было раньше;
- пользователь мог зайти, запросить данные доски из БД и быть уверенным в том, что эти данные актуальны, без ожидания синхронизации с другими пользователями.
Цифры внутри банка за два года:
- > 75 тысяч досок;
- > 30 тысяч пользователей;
- 3,5 тысячи уникальных пользователей в день;
- сравнительно небольшой объем данных: 400 ГБ;
- 80 RPS в пике.

Архитектурную схему можно посмотреть и в Unidraw.