Engineering notes

Build notes from a solo office suite.

Technical posts from the work in Casual Sheets, Casual Editor, and Casual Slides. Yjs CRDT bridges, Hocuspocus production patterns, .xlsx + .pptx round-trip lessons, capacity modelling, and the production-readiness work behind each release. No marketing — just what shipped and why.

Subscribe via RSS.

  1. Casual Sheets May 28, 2026

    Measuring the WebSocket broadcast ceiling of a single Node process

    We modelled the broadcast ceiling of a Hocuspocus + Yjs CRDT backend at ~500 active docs per Node process. Then we measured it. The model was 10× too conservative — the real bottleneck is somewhere else entirely.

    hocuspocusyjswebsocketload-testingcapacity-planningnode
    Read →
  2. Casual Sheets May 28, 2026

    Load testing without k6: a 190-line Node-only HTTP harness

    Before you reach for k6 or artillery, try a Node script. Built-in fetch + perf_hooks gives you p50/p95/p99 in 190 lines, zero new dependencies, and runs anywhere Node runs. Real numbers from the Casual Sheets v0.2.0 production-readiness pass.

    load-testingnodefetchperfbenchmarkingcapacity-planning
    Read →
  3. Casual Sheets May 28, 2026

    Yjs replay retry: classifying transient vs permanent failures in a CRDT bridge

    When a Yjs CRDT bridge fails to apply a remote mutation, the difference between "network blip during chunk-load" and "malformed mutation params" matters a lot. We added a 50-line classifier and a 4-second retry budget. Silent divergences became user-visible recoverable state.

    yjshocuspocuscrdterror-handlingcollaborative-editingproduction
    Read →
  4. Casual Sheets May 28, 2026

    Rate limiting and room caps for a Hocuspocus + Fastify backend

    A production-readiness pass on a Yjs realtime backend: per-route token-bucket rate limiting via @fastify/rate-limit, a MAX_ROOMS cap with two-pass LRU eviction, and a 503 capacity_full envelope. Three small pieces that turn "denial-of-service-by-loop" into "tight-but-bounded write surface."

    fastifyhocuspocusrate-limitingproductionbackend-hardeningyjs
    Read →
  5. Casual Sheets May 27, 2026

    When deepRewriteUnitId isn't deep enough: a Yjs CRDT bridge bug

    A cross-peer drawing sync bug in a Yjs + Hocuspocus collaborative spreadsheet. The fix wasn't where we expected. A story about positional arrays, json1 op paths, and why "the skipped test header explains the bug" is a comforting lie.

    yjshocuspocuscrdtcollaborative-editingbug-fixjson1
    Read →