Decision: Keep the Markdown engine in Rust + WASM

Recurring conversation that I'm now closing.

The question that keeps coming up

"Why not just use remark / markdown-it / marked? They run in JS, no WASM boundary, no Rust build step."

The answer

We've measured this three times across the last six months. The Rust + WASM build via comrak is:

  • 2.3x faster on cold render (a 200KB doc renders in 4.1ms vs ~9.5ms for remark)
  • Reference-correct on GFM. remark's plugin stack drifts on tables, task lists, and footnotes in ways we hit in user reports.
  • Stable. The build is cargo build --target wasm32-unknown-unknown + wasm-bindgen. Three commands. The CI pipeline is 38 seconds end to end.

The friction:

  • We can't use syntect (the C bindings don't compile to WASM cleanly). Highlighting moved client-side to highlight.js. That's a Phase 1 paper cut that became permanent. Fine.
  • wasm-opt is in our release profile because the current upstream rejects bulk-memory operations that LLVM emits. We accept the ~8% size hit until the toolchain catches up.

The case I'd entertain re-litigating

If markdown-rs (also Rust → WASM) caught up to comrak on GFM fidelity AND shipped TypeScript types, we'd evaluate. As of 2026-Q2 it's not there. Saved as a watch item.

Receipts

  • Bench harness: packages/engine/benches/render.rs (16 test docs, p95 across 1000 runs)
  • The last argument I had with myself about this: 2026-02-14, when I was tired and considered punting WASM. The 30-min experiment that morning settled it: marked.parse(largeDoc) blocked the main thread for 80ms+. The WASM call doesn't.