Q2 2021
Micro-Monoliths and Decentralized Compute
I'm at a crossroads and I need infrastructure to ship even a simple game. The enjoyable path is building it all myself -- gossip failure detection, raft replication, the whole empire. The wise path is to not worry about scale or durability for a five-minute game and just use MySQL on the host. I know which path I should take. I also know which path I want to take.
This is where DFINITY's Internet Computer entered my thinking. Their canister concept is almost the perfect infrastructure for Adama. A canister is a stateful application running WebAssembly, made durable via replication of a log of messages (the blockchain), where state is the deterministic result of ingesting those messages. This is very similar to an Adama document -- stateful, message-fed, deterministic.
But there are differences that matter. Adama doesn't address the graph element yet: what does it mean for two documents to talk to each other? I have three reasons for avoiding this. First, asynchronous behavior between documents requires error handling, and a design goal of Adama is to eliminate as much failure handling as possible -- no disk, no network failures from the developer's perspective. Second, I don't believe direct message exchange is compatible with reactivity. Instead of two documents sending commands, I'd rather have one document export a reactive view to another, collapsing error handling to "the data has or hasn't arrived." Third, machines can generate messages without limit, so unbound queues are a risk that reactivity and flow control solve more naturally.
The canister's access control model mirrors Adama's -- each container is a self-enclosed security boundary using principals. No external ACL needed. Each document has @connected for authorization, privacy controls on data fields, and the constructor for initialization around a creator principal. The big difference is the read side: Adama clients get data pushed to them automatically, filtered by privacy rules, without asking for it explicitly.
The cost model is elegant on both sides. The Adama language solved the halting problem for its domain -- a finite budget means the program stops when you're broke. State is transactional, so you can roll back. The canister's all-or-nothing billing model implies similar transactional guarantees.
Thinking about canisters led me to enumerate the actor types any serious platform needs: data primary actors for writes, stateless routers, aggregator actors for cross-shard reports, ephemeral replica actors for fan-out, fan-in reducer actors for view counters, web server actors for front-ends. Building a new internet requires rethinking how old world ideas transform into new primitives.
But the more I thought about decentralized compute, the more I started thinking about something closer to home: micro-monoliths.
The industry is drunk on Docker, Kubernetes, and micro-services. All the cool kids want super scalable architectures, cargo culting practices that only make sense with hundreds of engineers. As the guy who generally cleans up messes and makes services reliable, I have a bipolar relationship with micro-services. On one hand, they solve real people problems -- engineers can scope and focus their world view. On the other hand, the cost manifests in extra machines, and everyone must understand that networks are not perfectly reliable. A bunch of stateless services sounds great until failures mount and your reliability sucks.
Monoliths enable more reliable software (less moving pieces), but slow build times and hard release schedules make them undesirable because people. The tradeoff is always between hardware costs and people costs.
This is where WebAssembly enters the picture. You can recreate a monolith with WebAssembly containers that can be changed during normal operation. This is a "micro-monolith" -- fitting as many conceptual services within a single machine as possible, getting the people benefits of micro-services with a monolithic runtime. This thinking mirrors mainframes where hardware can be replaced while the machine is running.
The potential is real. Removing the need to serialize requests, queue a write, let the network do magic, read from a network queue, and deserialize -- that eliminates CPU work, decreases latency, increases reliability, and reduces heap and GC pressure. A fleet of stateless services suddenly feels pointless and wasteful of network resources.
These ideas are not new. The actor model, Erlang, BEAM VM -- spiritual alignment everywhere. I've come to believe this mode of programming is superior (as many Erlang zealots would promote), but it has been held back by languages. WebAssembly feels like the escape from that dogma.
So what do I do? I could build a "state-machine/actor as a service" business, similar to Cloudflare's Durable Objects but with a WebSocket hooked up and a streaming protocol. It would feel like Firebase but far more expressive -- you'd build your own database operations within the document. Is there an open-source Firebase? (There should be.)
The Adama language itself will take tremendous time to finish in quality, features, tooling, and documentation. Programming languages gain religious zeal, and it tends to be better to focus on making either a great library or a service with a solid API. If the goal is to align and lead industry, building an infrastructure business around WebAssembly where people bring their own language might work better. But then I'd lose the thing that makes Adama special -- the language is the product because it makes the hard things (persistence, privacy, reactivity, state synchronization) invisible.
The clear next step is to figure out a WebAssembly strategy for 2022/2023 that could enable offloading infrastructure to someone else's cloud. Keep infrastructure investments low. Focus on killer products. Use block storage and hope blocks don't go poof. Integrate S3 for cold state backup. Accept that machine failures mean availability loss for now.
This is an exciting time to be alive. What will computing look like when both compute and storage are public utilities?