<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"><channel><title>Casual Office — Engineering notes</title><description>Technical posts from building open-source web spreadsheets, .docx editors, and slide decks. Yjs CRDT bridges, Hocuspocus, capacity modelling, .xlsx + .pptx round-trip, and the production-readiness work behind each release.</description><link>https://schnsrw.live/</link><language>en-us</language><item><title>Measuring the WebSocket broadcast ceiling of a single Node process</title><link>https://schnsrw.live/notes/websocket-broadcast-ceiling-single-node-process/</link><guid isPermaLink="true">https://schnsrw.live/notes/websocket-broadcast-ceiling-single-node-process/</guid><description>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.</description><pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate><category>hocuspocus</category><category>yjs</category><category>websocket</category><category>load-testing</category><category>capacity-planning</category><category>node</category></item><item><title>Load testing without k6: a 190-line Node-only HTTP harness</title><link>https://schnsrw.live/notes/http-load-harness-without-k6/</link><guid isPermaLink="true">https://schnsrw.live/notes/http-load-harness-without-k6/</guid><description>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.</description><pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate><category>load-testing</category><category>node</category><category>fetch</category><category>perf</category><category>benchmarking</category><category>capacity-planning</category></item><item><title>Yjs replay retry: classifying transient vs permanent failures in a CRDT bridge</title><link>https://schnsrw.live/notes/yjs-replay-retry-transient-vs-permanent/</link><guid isPermaLink="true">https://schnsrw.live/notes/yjs-replay-retry-transient-vs-permanent/</guid><description>When a Yjs CRDT bridge fails to apply a remote mutation, the difference between &quot;network blip during chunk-load&quot; and &quot;malformed mutation params&quot; matters a lot. We added a 50-line classifier and a 4-second retry budget. Silent divergences became user-visible recoverable state.</description><pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate><category>yjs</category><category>hocuspocus</category><category>crdt</category><category>error-handling</category><category>collaborative-editing</category><category>production</category></item><item><title>Rate limiting and room caps for a Hocuspocus + Fastify backend</title><link>https://schnsrw.live/notes/rate-limit-room-cap-hocuspocus-backend/</link><guid isPermaLink="true">https://schnsrw.live/notes/rate-limit-room-cap-hocuspocus-backend/</guid><description>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 &quot;denial-of-service-by-loop&quot; into &quot;tight-but-bounded write surface.&quot;</description><pubDate>Thu, 28 May 2026 00:00:00 GMT</pubDate><category>fastify</category><category>hocuspocus</category><category>rate-limiting</category><category>production</category><category>backend-hardening</category><category>yjs</category></item><item><title>When deepRewriteUnitId isn&apos;t deep enough: a Yjs CRDT bridge bug</title><link>https://schnsrw.live/notes/drawing-sync-json1-op-path/</link><guid isPermaLink="true">https://schnsrw.live/notes/drawing-sync-json1-op-path/</guid><description>A cross-peer drawing sync bug in a Yjs + Hocuspocus collaborative spreadsheet. The fix wasn&apos;t where we expected. A story about positional arrays, json1 op paths, and why &quot;the skipped test header explains the bug&quot; is a comforting lie.</description><pubDate>Wed, 27 May 2026 00:00:00 GMT</pubDate><category>yjs</category><category>hocuspocus</category><category>crdt</category><category>collaborative-editing</category><category>bug-fix</category><category>json1</category></item></channel></rss>