All projects

Reactive database platform

Our own reactive BaaS on native SpacetimeDB — ~200k realtime deliveries/s at p95<20ms.

RustSpacetimeDBRealtime BaaS
01

Challenge

We wanted the developer experience of a reactive backend — live queries, a typed client and server — but a single-Node runtime tops out around 25-30k realtime deliveries/s, and we did not want to depend on a rented backend.

02

What we did

Our own reactive BaaS with a native SpacetimeDB transactional/realtime engine inside: a compiler turns our schema and functions into an STDB module, a compatibility layer keeps the same client and server API our apps already use (ideally the same client, a different URL), and a worker handles actions and external I/O (Stripe, email, LLM, webhooks); the surface is proven to carry zero production dependency on the reference implementation, which stays only as a differential-test oracle.

03

Result

Existing apps move over with little more than a URL change, onto an engine that holds ~200k realtime deliveries/s at p95<20ms — roughly 7x per box over the old runtime, without the Node ceiling.

Dev-story article

Reactive database platform: how the project was built

Every one of our apps wants the same thing from a backend: live queries, a typed client and server functions, without a rented product in the middle. We already had a reactive BaaS running on a single Node thread, and it worked — until the fanout numbers stopped being comfortable. This is the next implementation of that exact product, with a native SpacetimeDB engine inside, under one hard rule: the apps must not have to change.

Sections

05

Modules

05

Stack

Rust + SpacetimeDB

01

Why the project exists

We wanted the developer experience of a reactive backend — live queries, a typed client and server — but a single-Node runtime tops out around 25-30k realtime deliveries/s, and we did not want to depend on a rented backend.

Every one of our apps wants the same thing from a backend: live queries, a typed client and server functions, without a rented product in the middle. We already had a reactive BaaS running on a single Node thread, and it worked — until the fanout numbers stopped being comfortable. This is the next implementation of that exact product, with a native SpacetimeDB engine inside, under one hard rule: the apps must not have to change.

02

What was built

Our own reactive BaaS with a native SpacetimeDB transactional/realtime engine inside: a compiler turns our schema and functions into an STDB module, a compatibility layer keeps the same client and server API our apps already use (ideally the same client, a different URL), and a worker handles actions and external I/O (Stripe, email, LLM, webhooks); the surface is proven to carry zero production dependency on the reference implementation, which stays only as a differential-test oracle.

A compiler turns our schema and functions into a native SpacetimeDB module (Rust), so transactions and realtime run on an engine built for exactly that. A compatibility layer re-implements the same client and server API our apps already speak — the ideal is the same client library pointed at a different URL. A worker handles actions and external I/O (Stripe, email, LLM, webhooks) outside the transactional core, and a dashboard covers schema, data and logs. The old single-Node stack stays as a working fallback until a proven cutover.

03

Main modules and user path

M01

The reason for the rewrite is a number: the old single-Node runtime tops out around 25-30k realtime deliveries/s, while a native engine holds ~200k at p95<20ms — roughly 7x per box. The whole design exists to reach that ceiling without reintroducing the Node bottleneck in the compatibility path.

M02

Independence is treated as something to prove, not claim: a machine scanner walks every production dependency, and a dedicated gate runs the corpus with the reference package physically removed. The gate is red first — the very first receipt shows it failing before the work — and only turns green once the production surface genuinely does not import the reference implementation.

M03

Compatibility is verified differentially: a minimal reference app runs against both engines and the outputs are compared, so the reference implementation ends up as a test oracle rather than a runtime dependency.

M04

The wire codec is our own, not borrowed from the reference package, so even the browser client stops pulling that package into production — down to error identification matching the official behavior by signal.

M05

Code generation and new projects target our own packages; the reference API stays only as a compatibility and oracle surface. Migrating an existing app is meant to be a URL change, and the parity corpus (16/16 and 18/18 on the release gates) is what backs that claim.

04

Architecture and technology decisions

Built with Rust, SpacetimeDB, Realtime BaaS.

A Rust SpacetimeDB module for schema and reducers; a compiler from our schema and functions to that module; a compatibility layer for the client and server API; our own wire codec; a Node control-plane gateway (dashboard and deploy) for low-traffic operations; a worker for actions and external I/O; and parity fixtures, benchmarks and independence gates in CI.

05

Result and lessons

Existing apps move over with little more than a URL change, onto an engine that holds ~200k realtime deliveries/s at p95<20ms — roughly 7x per box over the old runtime, without the Node ceiling.

Our apps get a reactive backend we own end to end, on an engine that holds ~200k realtime deliveries/s at p95<20ms, with the same live-query model developers expect — and a migration that is meant to be a URL change, backed by a green independence gate rather than a promise.

Read next

These projects share nearby technical or product decisions, so they show how the same principle behaves in another context.

Have a similar idea?

Discuss your project