Design notes
Long-form, dated notes on what was built and measured, what was refused and why, and the post-mortems, kept as written.
- A conformance-suite tier
The server is pinned by hand-written probes against the RFC text -- smoke-ws speaks RFC 6455 from stdlib sockets, test_parsing.mojo covers the smuggling shapes directly -- and by no external suite on any cadence. A…
- The desktop-Mac server, and what the wheel gives up to ship
position may be as a desktop server — a Mac mini or Studio running an application on hardware someone already owns — rather than as a Linux container competing with Granian and uvicorn on rps. The reasoning is that…
- The Django server aims
Where the WSGI work is headed, and what gates each step — the full analysis with evidence is the design
- The drain does not read a request body in flight — resolved
Found by the soak driver's uploads population on color-separation (2026-09-02): with 9.7 MB multipart uploads in flight, every SIGTERM drain took exactly its 5 s budget, and the bisection put it on uploads alone.…
- v0.1.0: the first release
backpressure and Last-Event-ID replay, auth, CORS, config, health, JSON-lines access logging, graceful shutdown, multi-worker fork
- Hold on a pool thread: the refusal that keeps --realtime off real applications
(REAL_APP_VALIDATION.md, 2026-08-26) showed the realtime mode is not deployable for the application class it exists for, and the reason is a refusal this server makes on purpose: --realtime refuses --blocking-threads,…
- Inbound WebSocket flow control — shipped 2026-08-31
The outbound direction was credit-gated (websocket.send awaits its window) and the inbound direction had no backpressure of any kind. Once the executor's submit channel filled, WSGIHandler.ws_message discarded each…
- The loop inversion — in progress 2026-08-28
The handoff's item 1: run the Mojo loop's pass as a callback inside the executor's run_forever, on one thread, so a request goes parse → app → response with no datagram and no cross-thread wake. At c16 the pump batches…
- The Mojo handler pool — shipped 2026-08-28
The offload pool, for handlers written in Mojo. Planned as a kill-criterion spike: if a slow Mojo handler did not strand the connections behind it the way a slow Python view does, the branch was to be deleted and this…
- Mojo language capabilities, surveyed 2026-08-28
A pass over what the tree uses of the language, prompted by "are we fully tapping Mojo?". The short answer is yes wherever it was measured to pay — SoA span-based headers (+72%, the largest single win here), SIMD…
- The outbox sweep — taken, scoped (2026-08-29)
The second lever the inversion entry named. Every pass swept all 1,024 slots for a streaming one to drain, and the miss path — two flag loads per slot, none set — measured 1.2–1.3 µs per pass in isolation, on a pass…
- Proven once, unloaded: an inventory of the gates with that shape
The v0.15.1 bug came from a shape rather than an oversight: proven once, by a smoke, and stressed not at all. The measure of how little that guarantees is exact. Reverting the websocket.send credit gate was caught on…
- Pacing the pump's loop thread
What the sweep measurement exposed: at c16 the pump's throughput depends on how long its loop thread spends per pass, in a way that an accidental 1.2 µs improved by 3%. An explicit pause before flushing a partial batch…
- A request body still arriving at SIGTERM held the drain to its deadline — resolved
The drain loop read nothing new, so a half-received upload was neither completed nor closed until the 5 s budget expired: the client was reset and the process exited at 5.09 s. Found by the soak driver's uploads…
- Considered, not built: routes that carry a function
Router.match returns an Int and the caller dispatches on it, which is why three of five Mojo apps skip the router and hand-write if path == …. Route-to-function is reachable on Mojo 1.0 — verified by spike, not assumed.…
- Streamed WSGI bodies — shipped 2026-08-27
The last buffered shape. A generator the application did not size — Django's StreamingHttpResponse, the thing every Django SSE tutorial returns — was joined whole by the shim, so a never-ending one never answered and…
- Hardening the streaming seam — shipped 2026-08-27
0.14.0 shipped a fix for a hang that had been live all day: the shim keyed a connection slot's executor state — credit window, event, disconnect mark — by SLOT, while the loop recycles a slot the instant it closes a…
- Structured CI results
to $M0_RESULTS as one JSON line; the smoke job renders them into the run summary with a headroom column and uploads ci-results-<os>. Five sites are instrumented: the WSGI and ASGI RSS guards, the pool's fast-request…
- Traceability: stable ids, then declared coverage
SPEC.md is a requirements traceability matrix -- the standard artifact in safety-critical software, whose defining property is that it traces BOTH ways: every capability to its evidence, and every piece of evidence back…
- The WebSocket close path RSTing instead of FINning — resolved v0.15.1
Listed as a suspected race for two sightings, both on macOS CI and never locally. It was not a flake: RFC 6455 §5.5.1 requires the endpoint that sends Close to WAIT to receive one, and the loop closed as soon as its own…
- The WebSocket send window — shipped 2026-08-28
The one path above that an ordinary application reaches, made to work rather than merely to fail honestly. websocket.send had no window: an app faster than its client filled the loop's 64 KB per-slot outbox and every…
- WSGI vs ASGI: the design record
The obvious roadmap item after a conformance-tested WSGI host is an ASGI host. This document is the case for not building one now. The short form: ASGI answers two independent questions — how does Python code overlap…