47 lines
3.4 KiB
Markdown
47 lines
3.4 KiB
Markdown
---
|
||
tags: adr
|
||
status: accepted
|
||
date: "2026-06-16"
|
||
deciders: "[[Zef Hemel]]"
|
||
owner: "[[Zef Hemel]]"
|
||
lastReviewed: "2026-06-19"
|
||
dependsOn:
|
||
- "[[ADR/007 Core Application Logic on the Client]]"
|
||
related:
|
||
- "[[ADR/009 Client Build Toolchain]]"
|
||
- "[[ADR/002 Sync Engine]]"
|
||
references:
|
||
- 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|all application logic moved to 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|its own decision]].) This is further discussed in [On Tech Stacks](https://no.silverbullet.plus/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|plug]] logic and sandboxing mattered (pre-[[ADR/007 Core Application Logic on the Client|v2]]).
|
||
* 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](https://github.com/silverbulletmd/silverbullet/pull/1555). Rust backend: [PR2010](https://github.com/silverbulletmd/silverbullet/pull/2010).
|
||
* Blog: [On Tech Stacks](https://no.silverbullet.plus/tech-stacks) — the decision criteria behind these moves (avoid technology zoos, maturity, leverage, fun).
|