From big Kubers down to small GenServers

Underjord is a tiny, wholesome team doing Elixir consulting and contract work. If you like the writing you should really try the code. See our services for more information.

Me and the team had a meeting which we dedicated to talking about architecture. Sort of an ad-hoc exploration of patterns and concepts. How systems usually fit together. Which is mostly through various types of queues. And a bunch of common patterns like request/response, publish/subscribe and workers on a queue. And most request/response is essentially workers on a queue going in two directions.

This post was originally written as part of my newsletter which is a weekly thing that I’ve done for probably 5 years now. Reflections on tech, business, life and a bunch of Elixir. Easy way to keep up with my various .. things, as well.

These patterns are nearly fractal in that looking closer you see the pattern again further down. I think the queues kind of stop showing up when you go lower than the stack in memory but I don’t know enough about processors to be sure what happens down there. Maybe the electrons are really just lining up but I kind of doubt it.

I think this is why people confuse Kubernetes and Erlang for example. They operate and orchestrate systems made up of these patterns. But Kubers does it at the level of machines and containers (mostly, maybe call it fleet level) and Erlang does it at a level just slightly outside of the application level (system level? System is very overloaded as a term. I should consult the OSI model, but I won’t.). They share strategies, and some architectural shapes but the zoom dial is set to very different levels. Kubes is zoomed out a fair bit. Erlang is closer to the action.

And people correlate microservices and GenServers which is kind of accurate but not 1:1 either. A microservice can be a worker, a broker, or a server doing request/response. A GenServer can also be all those things. They can even be at the same level of abstraction, doing the same workload and then they are at the same level on the zoom dial. But of course making very different trade-offs in terms of overhead and isolation.

If you get familiar with fundamental patterns you will see them everywhere. And that becomes a way to grasp the architecture of things, whether internal to an application, parts of a larger system or just the pseudo-architecture sketched out on a whiteboard for how something needs to fit together.

This has a similar mouthfeel to me as some other unavoidable computer things do. There are no continuous streams in the digital realm, just bigger and smaller batch sizes and the associated latency/efficiency trade-offs. There is no difference between something being slow to respond or gone and in the end we just make a decision about the appropriate timeout. Just weird stuff where I want to go “but surely that can’t be it”.

Computers are kind of silly that way. Thankfully the can be very silly, very fast so it works out.

Did I miss a fundamental idea or pattern that you care about? Let me know on the fediverse via @lawik (or Bluesky) or via good ol email at lars@underjord.io. Thanks for reading.

Underjord is a 4 people team doing Elixir consulting and contract work. If you like the writing you should really try the code. See our services for more information.

Note: Or try the videos on the YouTube channel.