What the work required, and the decision each piece forced. A list of technologies proves nothing, so every entry below names the thing that had to be decided and what it was decided against. All of it is in the source.
D1 binds at most a hundred parameters per query. The upsert binds five per row, and a chunk size of forty written next to the limit meant every statement carried two hundred, so every run of every source failed on “too many SQL variables” and had done for months. The chunk is now derived from the limit rather than written beside it, so adding a column cannot quietly put it back over.
A room is addressed by name rather than by a generated id, so two players typing the same room string reach the same object without a lookup table anywhere. The class is declared in a migration as a SQLite-backed Durable Object, which puts the room's state and its storage in the same place as its WebSocket.
A view declared security_invoker runs as the original caller even when it sits inside a view the owner owns, so owner rights do not pass through it. Anything that genuinely has to cross the RLS boundary goes through a SECURITY DEFINER function instead, which is the only construct that actually changes who the query runs as.
A polling thread writes each reading straight to SQLite and hands the batch to the interface thread, so the database is never touched from the thread that draws.
A client's logo is their property, not the internet's, so the bucket is private and a link in an email cannot carry an admin key. The link carries its own expiry and an HMAC over it instead, and the signature is verified BEFORE the database lookup, so file ids cannot be walked by asking for them.
Signatures are compared with an XOR walk over the whole string rather than with ===, because an equality check returns early on the first wrong character and a wrong signature could then be guessed one character at a time from how long the answer took.
Visitor addresses are salted, hashed and truncated before they are written anywhere, so the log cannot identify anyone if it ever leaks.
The apex MX belongs to Apple and every address already forwards correctly, so sender records went on a send subdomain. Writing SPF at the apex would have broken mail that was working in order to add mail that was not. And a Worker has no TCP, so it cannot speak SMTP at all: an HTTP mail API is a requirement here, not a preference.
The database row is written before the mail is sent, and the response reports recorded and notified as two separate facts. A mail failure costs a notification. It never costs the enquiry.
Static assets are served through an assets binding on the same Worker that handles the dynamic routes, so there is one deploy and one origin rather than a site and an API that can drift apart.
Two different problems. The game needs every player in a room to see the same state, which is what the Durable Object is for. RemapWrap needs a phone to act as an input device for the desktop beside it, so it runs a local bridge on the network they already share and nothing leaves the building.
Installing a system-wide keyboard listener is the same machinery a keylogger uses. The documentation says exactly that, in those words, because a reader deciding whether to trust it is entitled to know before they install rather than after.
The installer resolves its scope at compile time rather than negotiating it at run time. The assisted installer carries a UAC relaunch and a scope-selection interface that initialise even during a silent install, which is machinery a package manager has no way to answer.
A daemon thread polls the fleet on a timer and hands batches to the interface thread through a queue, which the interface drains on its own clock. Nothing blocks the thread that draws.
The previous version ran a private asyncio loop with an aiohttp session and a thread-pool fallback behind it. The library underneath already did the concurrency with the standard library, so the loop, the optional dependency and the fallback path were all removed. Measured afterwards: no loss of speed. Three moving parts and one dependency gone for nothing in return except less to go wrong.
The products these came out of are on the work page. Writing, with the source of every excerpt linked, is at /writing/.