The more I get experienced as a software engineer and a developer, the more I like to keep things simple. In this article I will explain why I believe that boring - yet pragmatic - choices are often the most powerful.
Did you say "boring"?
I borrowed this term from a talk given by two Doctolib software engineers (Doctolib is a very successful french startup in the health space). In this presentation, Nicolas & Michel explain how Doctolib is dealing with 30k+ simultaneous users with a very simple and straightforward Ruby on Rails architecture: mostly a monolithic web application and a SQL database.
Before going deeper into software architecture, you may want to know that the boring trend has also been mentioned in quite a few other fields:
- LA Times journalist Christopher Hawthorne is praising boring building architecture in his "Boring architecture? Yes please" paper.
- Nick Rollins helps us to remember that a Good User Experience involves a Boring User Interface and urges not be creative when dealing with UI: don't mess with your users and just stick to the - boring - established standards.
- And even Elon Musk named his company The Boring Company ;-) (terrible example, they are actually boring, ie. drilling, tunnels)
Let's focus again on software architecture: a few years ago I wrote an article about the choice of not using any JS Framework when libraries such as Angular or EmberJS were on the rise, but instead leveraging on a very classic MVC architecture with a thin JS layer. I since had excellent feedbacks on this approach even if I occasionally rely on ReactJS to handle very dynamic pieces of UI.
Unfortunately it seems that my ideas are against the current flow, since average web applications kept getting more and more complex with:
- a lot of different storage solutions (NoSQL)
- GraphQL replacing REST APIs
- The rise of micro-services architectures (M/SOA)
- Containerized (Docker) and orchestrated deployments (Kubernetes)
These architectural solutions are impressive at helping large scale companies to deal with their storage or operation issues. But what drives me crazy is to see how many, seed or low-scale companies / softwares start using these technologies from the ground-up.
Micro Services architectures
Let's take an example : Micro Services. It looks so neat and clever on your PowerPoint slides, making you think you will divide and conquer on your software by splitting the big business problems you are trying to solve in much smaller pieces of software - easier to manage.
But M/SOA also induces a very important development overhead:
- If you want your micro-services to talk together, you'll have to tie them up with APIs (whereas a simple function call would have been much simpler and faster).
- You can't simply share code between your services. You'll have to build and release libraries shared between your micro-services, even for sharing a simple one-liner function across your services.
- Micro-services also mean multiple units of deployment, which is way more complicated to release and run than a single web application. People usually end up with solutions like Kubernetes.
- Versioning and release-management is really tough.
This overhead will eventually drive you away from delivering actual business value, which is not only a terrible idea for early stage companies, but a handicap for any size of business.
Another example is the use of document oriented databases (such as MongoDB or CouchDB). Such databases are designed with very attractive benefits compared to relational databases:
- you can store document (think JSON object) instead of simples rows.
- database is schema-less meaning a single collection (ie. table) can hold documents of different nature (new attributes ...) without any schema migration involved.
Unfortunately, what these databases are not marketed for, is the feature they lack regarding SQL databases:
- you cannot join different collections together. Meaning that if you want to reach best performance, your must really think your schema upfront considering all your use cases and potential queries to store and structure your documents in an optimal way. But your business will change and so will your queries ... leading you eventually to either sub-optimal N+1 queries or de-normalized data structures which are a nightmare to maintain, making you build over-engineered CQRS architectures (overhead!)
- no ACID transaction. You can live without it 90% of the time, but the remaining 10% are a real pain to work-around with software transaction and compensation mechanisms
I used MongoDB for years and learned these lessons the hard way at the expense of days at tweaking for improved performance and using CQRS design pattern to maintain integrity between denormalized data collections.
A few years later, when came the time to build a new product I adopted PostgreSQL and it was such a relief! Postgres even became stronger over years by including new features previously only available in some noSQL system (such as JSON column datatype, partitioning and sharding, or geographic search).
The Majestic Monolith
Monolithic software architectures sound awkward, clumsy - of course boring - and unable to face agile and fast changing requirements. But they are quite the opposite.
Doctolib previous example has already proven me right, but so did Basecamp. In The Majestic Monolith post DHH explains how Basecamp is dealing with million of users with their large and monolithic application.
Run a small team, not a tech behemoth? Embrace the monolith and make it majestic. You Deserve It! - DHH, 2019
Building your software as a monolith doesn't mean that you don't care about architecture and are willing to build a big plate of spaghetti-ware. I sincerely believe that removing the clutter and the boilerplate of non essential technology will help you at focusing on things that really matter such as a well designed business layer and tons of unit tests.
You can totally craft well-thought and battle-tested code in a - majestic - monolithic fashion
Some might argue that such a simplistic architecture does not add up very well with the size of their team or organization. Please look at it the other way around: maybe that if you started building less complicated software, you might figure out that you need smaller teams?
"Organizations which design systems are constrained to produce designs which are copies of the communication structures of these organizations" - Conway, 1967.
50 years ago, John Conway stated about the deep link existing between the structure of software and the structure of organizations which build them. So keep with small teams, hire jack-of-all-trades full-stack developers and build clean, simple and pragmatic software. I'm quite sure this advice should resonate with most companies building software ; not everyone is building Google or Facebook.
The patterns that make sense for organizations orders of magnitude larger than yours, are often the exact opposite ones that’ll make sense for you. It’s the essence of cargo culting. If I dance like these behemoths, surely I too will grow into one. I’m sorry, but that’s just not how the tango goes. - DHH, 2019
I don't know if building boring and simple softwares with smaller teams will become a new trend in upcoming years, but it is my motto since a few years and it gives strong results until now.
You might wonder "Will I get bored at building boring stuff? . I don't think you will:
- Building simple software does not mean at all being bored: you will deliver more value and joy to your users and it is among the most exciting things and what should fuel your days as a software developer.
- I'm still tech savvy and really interested in new technologies and frameworks, but I'm also getting older and wiser ;-) When considering a new technology I'm always thinking about the tradeoff between the provided value and the induced overhead.