While I’ve spent time in the last few weeks revisiting my startup diaries from 2017 and 2018, I feel it’s time now to explain microservices in a bit more depth. They represent an approach that may suit your company as you plan your MVP, or if you are technical and want to find out more, check out the 2nd edition of my book “The Tao of Microservices” (use discount code: au35rod for 35% off on the Manning site).
When you’ve been building systems using microservices for a few years you learn a lot from doing stupid stuff. I have done some very stupid stuff—herewith another war story!
When you have many microservices, you often get asked: “I have to fix this bug, where can I find such-and-such?” The such-and-such might be entity validation rules, entries for a UI drop-down, database connection details, cookie settings, whatever. In most systems, microservice or not, you will find this information sprawled all over the codebase, in configuration files in various formats, in source code, in the database, hard-coded in HTML, and even worse.
In a monolith it’s painful but not impossible to find things, and you get “used” to the code. Onboarding a new developer just takes time and that’s the way it has always been. In a microservice system, it’s a lot worse. Now you have to wonder which microservice code-base to look at (monorepos help a bit), and worse, you have to wonder if the information is consistent between services. Yikes. I can feel the Twitter monolith posse poised over their keyboards, ready to strike once again at the corporate overlords of Big-Microservice…
Well, they have a point. The problem of information fragmentation is endemic in large software systems regardless of architecture. One strange “advantage” of microservices is that it makes difficult things impossible. Yes, that is an advantage. There’s nowhere to hide and you have to be more deliberate and systematic.
I’ve mostly solved this information fragmentation problem using an approach I’m calling “model-as-code”. Inspired by “infrastructure-as-code” in general, and a great talk I saw by Joe Duffy of Pulumi, I started playing around with some sort of validated universal system description. This is almost like the JSON export you’d get from a no-code tool like bubble.io or retool.com - a full and complete definition of the system - in code.
Then I found cuelang.org and I knew I had a workable solution! Cuelang is a typed configuration language with some really neat semantics to avoid death-by-override in a million little files. We started defining almost everything about our system in a central model (hence “model-as-code”) that was shared among services. Now it was easy to keep everything consistent, and easy to answer the question: “Where do I find such-and-such?” - it’s in the model!
It’s very early days for this approach, and the tooling is still very hands-on, but it has already improved our developer experience no end! You don’t have to use the tools I’ve mentioned, like Cuelang. They are not that important. The key idea is to describe your system in one place, validate that description, and then use it to drive implementation. If you want to see a real-world implementation of this idea in a different context, check out the Godot game engine - we’re just doing the same thing for boring old business apps.
For more insights and honest experiences from tech experts, conference speakers and entrepreneurs, visit our podcast page.