Gillius's Programming

Don't be Afraid of the Monolith

19 Sep 2025

A common mistake I’ve seen is developers over-engineering new applications. While it can be partially caused by “ resume-driven design”, I feel it mostly comes from the assumption that the latest techniques seen online from large tech companies apply to everyone. Sure, the Googles and Facebooks of the world can be a great technical role model, but not every application has to be built like Netflix. I would even argue that a “next Netflix” shouldn’t be built initially like Netflix.

A city of 1,000 wouldn’t start with building airports, trains and highways even if it will become a city of 1 million. The same applies to software. Sure, consider the future of maximum scale, but new requirements and technologies will foil even the best plans. You just need to leave a way to evolve to the next stage.

A design pattern I see commonly abused in new projects is picking microservices over modular monolith. It’s hard to imagine a new application that should start its life as microservices. Even with a skilled team, the pressure to deliver the minimum viable product is strong enough such that there is a high risk of getting the worst of both worlds: a distributed monolith, or at best an over-designed and complex to debug system requiring dedicated DevOps engineers before you need them. In the beginning you should focus more on business requirements and value. I’ve seen this push to over-engineer many times – once, I was presented with a proposal to create a Kubernetes cluster for an application that otherwise ran with very little utilization on a single server with 1 vCPU and 4 GB memory.

Some rules of thumb that I have:

I recently came across an article “How to Scale an App up to 10 Million Users on Azure” by Dr Milan Milanović which is a great high-level software architecture discussion on an application’s lifecycle as it grows to global scale. The best part it reinforces: don’t be afraid to start small and simple. One of the essential tenets from this article is that you should scale architecture when a real pain point exists and not before.

Milan recommends starting with a modular modulith, and I agree. Modular monolith was called “good software design” prior to microservices, but as the term monolith got unconditionally disparaged during the microservices era, modular monolith differs from the poorly-designed “traditional” monolith of highly-dependent spaghetti code. Some developers assumed the then-new techniques like containers, CI/CD, canary testing and frameworks like Spring Boot came only in a microservices architecture; however, these great techniques still work in the monolith. A “modular monolith” enforces keeping modules small and to a single responsibility yet the application provides ways to scale with growth. Some frameworks have a way to enforce modular monoliths such as Spring Modulith. If you think the microservices pattern enforces good design, then consider doing the same with module boundaries instead of network boundaries and eliminate the complexities until requirements truly demand microservices, at which point turn the modules into microservices.

The whole article is worth a read and I agree with almost all of it. Here are my thoughts on it:

Overall, this is a great article explaining how an application can start from a humble beginning and grow to maximum scale. Hopefully our posts give you the encouragement not to over-design early, but understand enough about the process to leave an avenue for continuous improvement.

More reading by the same author:

Dev Version