Skip to content
Tech News
← Back to articles

120k Lines of Rust: Inside the Nosdesk Backend

read original more articles

120,000 Lines of Rust: Inside the Nosdesk Backend

Published: 28 May 2026

I wrote before about why I built Nosdesk, and somewhere in that story I said I chose the hard path with Rust and it paid off. That post was about the product. This one is about what powers it.

What started as a handful of files has grown, over a year or so, into something close to 120,000 lines of Rust across roughly 260 modules, with around 1,030 tests holding it in place. It still ships as a single binary that comes up with one docker compose up . The stack stayed deliberately small: Actix-web on top, Diesel over Postgres for storage, Redis for fan-out, Tokio running everything underneath.

Three habits ended up shaping the work, and they run through everything below:

Push the dangerous mistakes into the type system, so the wrong thing won’t compile instead of merely being discouraged. Split the pure logic from the I/O around it, so the tricky parts become functions you can test without a database or a socket. Make comments explain why, not what: the alternative I rejected, the RFC I’m honouring, the bug that taught me the lesson.

Everything Is a Pipeline

When a client connects to Nosdesk, the first thing it does is pull a full snapshot of everything it’s allowed to see (bootstrap sync), which on a real workspace is a lot of rows. Load that into a Vec and serialise it in one shot and you get a workspace-sized memory spike on every connection.

So bootstrap is a stream. Rows are serialised as newline-delimited JSON and pushed through an mpsc::channel(64) , so a slow reader back-pressures the producer instead of pinning the whole result set in RAM. Diesel is synchronous, which means the query side runs on spawn_blocking and the bytes come back through a ReceiverStream . The whole snapshot lives inside one transaction, so the client sees a consistent point-in-time view even while other writes are landing.

That shape repeats throughout the codebase: a bounded buffer, the blocking work pushed off the runtime, back-pressure as a feature. Once you see data flow as a pipeline where the producer can outrun its consumer, you stop writing code that falls over under load.

... continue reading