Q3 2022
Ever since I was in sixth grade, I've been drawn to the machine like a moth to the flame. Last year I turned 40 and completed six rounds of ketamine infusions. I had a spiritual experience -- launched into outer space, met Darth Vader, saw the entire multiverse as mathematical relationships. Life is a gift not to be squandered via nihilism nor cynicism. My purpose is to build Adama as a good work for the universe. Ars gratia artis.
But purpose needs plumbing, and this quarter the plumbing got interesting.
The first big move was breaking Adama documents out of their isolation with service calls. The motivation came from building the IDE with RxHTML -- just creating a space and document at the same time was problematic without server-side coordination. The less I wanted RxHTML and the front-end to do, the more I needed Adama to pick up the slack.
Service definitions landed in the parser:
service sms {
std = "http";
method<SendSMSRequest, SendSMSResponse> send;
}
A service is configuration aspects plus methods. Every service takes JSON in and emits JSON out. Methods can be invoked in reactive formulas, message handlers, procedures, and state machine transitions. But the first complication: side-effects. An SMS message has a brutal side-effect (it costs money and annoys people). Since formulas are ephemeral, reactivity could trigger cascading bad times. I built RxCache to deduplicate requests, but duplicate requests can still fire if a document changes hosts mid-request. Services must handle idempotence.
The second complication: once Adama could talk to itself, it became a full actor model implementation. An Adama document can receive messages from users and other documents, create other documents, and maintain relationships. But this unlocked a trust problem. A rogue developer could share a website to collect developer principals and then use those principals to call privileged APIs. I needed the type system to enforce trust boundaries.
The solution: bifurcate NtClient (which I should have called NtPrincipal from the start -- naming things is hard) into TyNativePrincipal and TyNativePrincipalTrusted. The @who expression gets the trusted type since it comes directly from Adama. Then grinding through every computational context:
| context | trusted service? | reason |
|---|---|---|
| message handler | no | data leakage via persistence |
| state machine transition | no | data leakage |
| bubble (view query) | yes | only viewable by the trusted user |
| web get | yes, but | unique per user, assuming no caching |
If the context can write to the document, it's a definitive no for reading sensitive data from other services. This turns Adama into a proxy that preserves trust at the user level.
Meanwhile, I was learning painful lessons about MQTT at scale. Having spent multiple years strangling MQTT at Meta (where I regrettably patented a new protocol), all manner of problems arise when you turn MQTT into a proxy for multiple subscription sources. The broker can't signal mid-stream death to the client. You either let subscriptions languish dead, invent a mini-protocol per product, or have the broker retry (losing messages during retry). Making subscriptions durable means maintaining a mapping of topics to subscribers -- which has caching problems, replication problems, and partial failure problems. Publish/subscribe just sucks if you care about reliability. MQTT is basically only good for unreliable sensor data.
Adama's approach: document differentials that batch and collapse on the server with a reliable ordered transport. Disconnect means sending the entire document again. The failure mode looks like polling. This means I could even leverage an unreliable transport like UDP with client-side reordering, which reframes how I think about MQTT as a business option: either clients deploy custom delta code (negating the point of MQTT) or the server sends full document snapshots with rate limiting (expensive but codeless). Neither option is free, so charge for bandwidth and memory.
The multi-region work became a mess. I had introduced cross-region database lookups at the web tier that added 150ms per hop. For a document warm in a remote region: 462ms. Unacceptable. The fix was moving the routing decision from the web tier to the Adama tier. Web hosts guess which Adama host has the document using consistent hashing. If the guess is right (99%+ of the time), you get a warm local connect in 12ms. If wrong, fall back to the database. Cold storage goes from 310ms to 162ms. The architecture requires a new "findbind" operation -- an atomic find-and-bind stored procedure.
I also thought about massive scale -- billions of devices. For reading personalized documents per viewer, hierarchical delta replication scales so long as the amplification fits within the outbound network card at each level. The last mile runs a specialized version of the Adama document with only the privacy logic. For writes from a billion devices, I'd define message reducers that combine a fire hose into a garden hose. The really hard problem is on-demand provisioning of the hierarchy in a multi-tenant environment. I don't have an answer yet.
And then there's the JavaScript ecosystem. The entire thing is garbage. If you've used any modern JavaScript tooling, you already know this. I chose JavaScript for BladeRunner out of spite because I knew it would be successful. The language is OK -- it's a glue language. The ecosystem is a dumpster fire. I had enough pain with Docusaurus that I switched to mdbook and Jekyll.
The entire front-end game is turning data into HTML. That's it. RxHTML is my answer: an exceptionally minimal framework where the key insight is reactivity as a primal infrastructure primitive. You don't need React if you have a reactive backend. The client is a stateless function of the server and local view state parameters. I'm living in this paradigm for the Adama portal, and it works. My thesis: I can radically simplify the engineering requirements for launching new businesses online.
My spiritual mission is to build a beacon of light to lead people out of the wasteland and into my cathedral.