Все проекты

Реактивная база данных

Наш реактивный BaaS на native SpacetimeDB — ~200k realtime-доставок/с, p95<20мс.

RustSpacetimeDBRealtime BaaS
01

Задача

Хотели удобство реактивного бэкенда — live-запросы, типизированный клиент и сервер — но однопоточный Node-рантайм упирается в ~25-30k realtime-доставок/с, и не хотели зависеть от арендованного бэкенда.

02

Что делали

Наш собственный реактивный BaaS с native SpacetimeDB как транзакционным/realtime-движком внутри: компилятор превращает нашу схему и функции в STDB-модуль, слой совместимости держит тот же клиентский и серверный API, который приложения уже используют (идеально — тот же клиент, другой URL), а worker ведёт actions и внешний I/O (Stripe, email, LLM, вебхуки); поверхность доказанно не имеет продовой зависимости от эталонной реализации, которая остаётся только оракулом для дифф-тестов.

03

Результат

Существующие приложения переезжают почти сменой URL, на движок, держащий ~200k realtime-доставок/с при p95<20мс — примерно 7x на бокс против старого рантайма, без потолка Node.

Dev-story статья

Реактивная база данных: как создавался проект

Каждое наше приложение хочет от бэкенда одного: live-запросов, типизированного клиента и серверных функций, без арендованного продукта посередине. У нас уже был реактивный BaaS на одном Node-потоке, и он работал — пока цифры fanout не перестали быть комфортными. Это та же реализация продукта заново, с native SpacetimeDB внутри, по одному жёсткому правилу: приложения не должны меняться.

Разделы

05

Модули

05

Стек

Rust + SpacetimeDB

01

Почему появился проект

Хотели удобство реактивного бэкенда — live-запросы, типизированный клиент и сервер — но однопоточный Node-рантайм упирается в ~25-30k realtime-доставок/с, и не хотели зависеть от арендованного бэкенда.

Каждое наше приложение хочет от бэкенда одного: live-запросов, типизированного клиента и серверных функций, без арендованного продукта посередине. У нас уже был реактивный BaaS на одном Node-потоке, и он работал — пока цифры fanout не перестали быть комфортными. Это та же реализация продукта заново, с native SpacetimeDB внутри, по одному жёсткому правилу: приложения не должны меняться.

02

Что было создано

Наш собственный реактивный BaaS с native SpacetimeDB как транзакционным/realtime-движком внутри: компилятор превращает нашу схему и функции в STDB-модуль, слой совместимости держит тот же клиентский и серверный API, который приложения уже используют (идеально — тот же клиент, другой URL), а worker ведёт actions и внешний I/O (Stripe, email, LLM, вебхуки); поверхность доказанно не имеет продовой зависимости от эталонной реализации, которая остаётся только оракулом для дифф-тестов.

Компилятор превращает нашу схему и функции в native SpacetimeDB-модуль (Rust), так что транзакции и реальное время крутятся на движке, сделанном именно для этого. Слой совместимости заново реализует тот же клиентский и серверный API, который приложения уже знают — идеал это та же клиентская библиотека, направленная на другой URL. Worker ведёт actions и внешний I/O (Stripe, email, LLM, вебхуки) вне транзакционного ядра, а дашборд показывает схему, данные и логи. Старый Node-стек остаётся рабочим фолбэком до доказанного cutover.

03

Основные модули и путь пользователя

M01

Причина переписывания это число: старый Node-рантайм упирается в ~25-30k realtime-доставок/с, а native-движок держит ~200k при p95<20мс — примерно 7x на бокс. Весь дизайн существует, чтобы достичь этого потолка, не вернув Node-узкое место в путь совместимости.

M02

Независимость считается тем, что надо доказать, а не заявить: машинный сканер обходит каждую продовую зависимость, а отдельный гейт гоняет корпус с физически удалённым эталонным пакетом. Гейт сначала красный — первая же квитанция показывает его падение до работы — и зелёным становится только когда продовая поверхность действительно не импортирует эталонную реализацию.

M03

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

M04

Wire-кодек у нас свой, не заимствованный из эталонного пакета, так что даже браузерный клиент перестаёт тянуть этот пакет в продакшн — вплоть до опознания ошибки, совпадающего с официальным поведением по сигналу.

M05

Кодогенерация и новые проекты целятся в наши собственные пакеты; эталонный API остаётся только поверхностью совместимости и оракула. Перенос существующего приложения должен быть сменой URL, а корпус паритета (16/16 и 18/18 на релизных гейтах) это подкрепляет.

04

Архитектура и технологические решения

Сделано на Rust, SpacetimeDB, Realtime BaaS.

Rust SpacetimeDB-модуль для схемы и редьюсеров; компилятор из нашей схемы и функций в этот модуль; слой совместимости для клиентского и серверного API; свой wire-кодек; Node control-plane gateway (дашборд и деплой) для операций с малым трафиком; worker для actions и внешнего I/O; и паритетные фикстуры, бенчмарки и гейты независимости в CI.

05

Результат и выводы

Существующие приложения переезжают почти сменой URL, на движок, держащий ~200k realtime-доставок/с при p95<20мс — примерно 7x на бокс против старого рантайма, без потолка Node.

Наши приложения получают реактивный бэкенд, которым мы владеем целиком, на движке, держащем ~200k realtime-доставок/с при p95<20мс, с той же моделью live-запросов — и переносом, который должен быть сменой URL, подкреплённым зелёным гейтом независимости, а не обещанием.

Читать дальше

Эти проекты близки по техническим или продуктовым решениям и показывают, как тот же принцип работает в другом контексте.

Есть похожая идея?

Обсудить проект