Files
plainleaf/docs/ADR/010 Rust Backend.md
T

3.4 KiB
Raw Blame History

tags, status, date, deciders, owner, lastReviewed, dependsOn, related, references
tags status date deciders owner lastReviewed dependsOn related references
adr accepted 2026-06-16 Zef Hemel Zef Hemel 2026-06-19
ADR/007 Core Application Logic on the Client
ADR/009 Client Build Toolchain
ADR/002 Sync Engine
bin/silverbullet/src/server.rs
server-common/src/space.rs
server-runtime-chrome/src/supervisor.rs

Context

The server does very little. Since ADR/007 Core Application Logic on the Client, the server is primarily a file store: it lists, reads, writes and deletes files, handles authentication, serves the static client, and runs shell commands. When the Runtime API is enabled, it manages a Chrome sub-process and delegates calls to it. This makes the server's implementation language a relatively low-stakes, swappable choice, and over the project’s life it has changed several times.

The server has been, in turn: Node.js (earliest prototypes), then Deno for years, then Go (2025), and now Rust (2026). (The separate move of the client build toolchain from Deno to Node is ADR/009 Client Build Toolchain.) This is further discussed in On Tech Stacks.

Decision

The server is written in Rust (as of v2.10.0). The progression was Node.js -> Deno -> Go -> Rust:

  • Deno: a modern, secure-by-default TypeScript runtime; a sensible fit while the server still ran Plugs logic and sandboxing mattered (pre-ADR/007 Core Application Logic on the Client).
  • Go (2025): once the server was just a file store, it was rewritten in Go: "significantly less memory and significantly smaller in size."
  • Rust (2026): the Go server was replaced by an adaptation of the Rust backend used elsewhere in the project, converging the whole codebase on TypeScript + Rust.

Consequences

Positive

  • Fewer languages. The stack converged from TypeScript + Go + Rust to just TypeScript + Rust: less to master and one backend to maintain.
  • Leaner runtime. Rust has no garbage collector and produces a small, single statically-compiled binary; memory use drops again.
  • Opens new doors. A Rust backend makes a future CRDT-based sync engine / real-time collaboration feasible where the Go ecosystem made it impractical — see ADR/002 Sync Engine.

Negative / trade-offs

  • Churn. Three server rewrites is real effort, and for a while two backends were maintained in parallel before converging.
  • Steeper language. Rust has a higher learning curve than Go or TypeScript, raising the bar for backend contributors. However, contributions to the backend were rare anyway, and generally unnecessary.

Alternatives considered

  • Revert the server to TypeScript (Deno or Node). Rejected: a JS runtime buys little for a process that just serves files and it is resource heavy.
  • Stay on Go. Rejected: Go meant maintaining a backend separate from the project's Rust code, and its ecosystem made the desired CRDT direction impractical.

References

  • Go backend: PR1555. Rust backend: PR2010.
  • Blog: On Tech Stacks — the decision criteria behind these moves (avoid technology zoos, maturity, leverage, fun).