<story><title>In Defense of Simple Architectures (2022)</title><url>https://danluu.com/simple-architectures/</url></story><parent_chain><item><author>lll-o-lll</author><text>&amp;gt; I&amp;#x27;ve never really understood why you couldn&amp;#x27;t just break up your monolith into modules&lt;p&gt;You can! We used to do this! Some of us still do this!&lt;p&gt;It is, however, much more difficult. Not difficult technically, but difficult because it requires discipline. The organisations I’ve worked at that have achieved this always had some form of dictator who could enforce the separation.&lt;p&gt;Look at the work done by John Lakos (and various books), to see how well this can work. Bloomberg did it, so can you!&lt;p&gt;Creating a network partition makes your system a distributed system. There are times you need this, but the tradeoff is at least an order of magnitude increase in complexity. These days we have a &lt;i&gt;lot&lt;/i&gt; of tooling to help manage this complexity, but it’s still there. The combination of possible failure states is exponential.&lt;p&gt;Having said all this, the micro service architecture does have the advantage of being an easy way to enforce modularity and does not require the strict discipline required in a monolith. For some companies, this might be the better tradeoff.</text></item><item><author>camgunz</author><text>&amp;gt; Services, or even microservices, are more of a strategy to allow teams to scale than services or products to scale.&lt;p&gt;I&amp;#x27;ve never really understood why you couldn&amp;#x27;t just break up your monolith into modules. So like if there&amp;#x27;s a &amp;quot;payments&amp;quot; section, why isn&amp;#x27;t that API stabilized? I think all the potential pitfalls (coupling, no commitment to compatibility) are there for monoliths and microservices, the difference is in the processes.&lt;p&gt;For example, microservices export some kind of API over REST&amp;#x2F;GraphQL&amp;#x2F;gRPC which they can have SDKs for, they can version them, etc. Why can&amp;#x27;t you just define interfaces to modules within your monolith? You can generate API docs, you can version interfaces, you can make completely new versions, etc.&lt;p&gt;I just feel like this would be a huge improvement:&lt;p&gt;- It&amp;#x27;s so much more engineering work to build the service handler scaffolding (validation, serialization&amp;#x2F;deserialization, defining errors)&lt;p&gt;- You avoid the runtime overhead of serialiation&amp;#x2F;deserialization and network latency&lt;p&gt;- You don&amp;#x27;t need to build SDKs&amp;#x2F;generate protobufs&amp;#x2F;generate clients&amp;#x2F;etc.&lt;p&gt;- You never have the problem of &amp;quot;is anyone using this service?&amp;quot; because you can use code coverage tools&lt;p&gt;- Deployment is much, much simpler&lt;p&gt;- You never have the problem of &amp;quot;we have to support this old--sometimes broken--functionality because this old service we can&amp;#x27;t modify depends on it&amp;quot;. This is a really undersold point: maybe it&amp;#x27;s true that microservice architectures let engineers &lt;i&gt;build&lt;/i&gt; things without regard for other teams, but they can&amp;#x27;t &lt;i&gt;remove&lt;/i&gt; things without regard for other teams, and this dynamic is like a no limit credit card for tech debt. Do you keep that service around as it slowly accretes more and more code it can&amp;#x27;t delete? Do you fork a new service w&amp;#x2F;o the legacy code and watch your fleet of microservices grow ever larger?&lt;p&gt;- You never have the problem of &amp;quot;how do we update the version of Node on 50 microservices?&amp;quot;</text></item><item><author>scient</author><text>Services, or even microservices, are more of a strategy to allow teams to scale than services or products to scale. I think thats one of the biggest misconceptions for engineers. On the other end you have the monorepo crew, who are doing it for the same reasons.&lt;p&gt;On your note about resiliency and scale - its always a waste of money until shit hits the fan. Then you really pay for it.</text></item><item><author>from-nibly</author><text>This is what I tell engineers. Microservices aren&amp;#x27;t a performance strategy. They are a POTENTIAL cost saving strategy against performance. And an engineering coordination strategy.&lt;p&gt;Theoretically If you have a monolith that can be scaled horizontally there isn&amp;#x27;t any difference between having 10 replicas of your monolith and having 5 replicas of two microservices with the same codebase. UNLESS you are trying to underscale part of your functionality.  You can&amp;#x27;t underscale part of your app with a monolith. Your pipe has to be big enough for all of it. Generally speaking though if you are talking about 10 replicas of something there&amp;#x27;s very little money to be saved anywhere.&lt;p&gt;Even then though the cost savings only start at large scales. You need to have a minimum of 3 replicas for resiliency. If those 3 replicas are too big for your scale then you are just wasting money.&lt;p&gt;The place where I see any real world benefit for most companies is just engineering coordination. With a single repo for a monolith I can make 1 team own that repo and tell them it&amp;#x27;s their responsibility to keep it clean. In a shared monolith however 0 people own it because everyone owns it and the repo becomes a disaster faster than you can say &amp;quot;we need enterprise caching&amp;quot;.</text></item></parent_chain><comment><author>default-kramer</author><text>&amp;gt; easy way to enforce modularity and does not require the strict discipline required in a monolith&lt;p&gt;In my experience, microservices require &lt;i&gt;more&lt;/i&gt; discipline than monoliths. If you do a microservice architecture without discipline you end up with the &amp;quot;distributed monolith&amp;quot; pattern and now you have the worst of both worlds.</text></comment>
<story><title>In Defense of Simple Architectures (2022)</title><url>https://danluu.com/simple-architectures/</url></story><parent_chain><item><author>lll-o-lll</author><text>&amp;gt; I&amp;#x27;ve never really understood why you couldn&amp;#x27;t just break up your monolith into modules&lt;p&gt;You can! We used to do this! Some of us still do this!&lt;p&gt;It is, however, much more difficult. Not difficult technically, but difficult because it requires discipline. The organisations I’ve worked at that have achieved this always had some form of dictator who could enforce the separation.&lt;p&gt;Look at the work done by John Lakos (and various books), to see how well this can work. Bloomberg did it, so can you!&lt;p&gt;Creating a network partition makes your system a distributed system. There are times you need this, but the tradeoff is at least an order of magnitude increase in complexity. These days we have a &lt;i&gt;lot&lt;/i&gt; of tooling to help manage this complexity, but it’s still there. The combination of possible failure states is exponential.&lt;p&gt;Having said all this, the micro service architecture does have the advantage of being an easy way to enforce modularity and does not require the strict discipline required in a monolith. For some companies, this might be the better tradeoff.</text></item><item><author>camgunz</author><text>&amp;gt; Services, or even microservices, are more of a strategy to allow teams to scale than services or products to scale.&lt;p&gt;I&amp;#x27;ve never really understood why you couldn&amp;#x27;t just break up your monolith into modules. So like if there&amp;#x27;s a &amp;quot;payments&amp;quot; section, why isn&amp;#x27;t that API stabilized? I think all the potential pitfalls (coupling, no commitment to compatibility) are there for monoliths and microservices, the difference is in the processes.&lt;p&gt;For example, microservices export some kind of API over REST&amp;#x2F;GraphQL&amp;#x2F;gRPC which they can have SDKs for, they can version them, etc. Why can&amp;#x27;t you just define interfaces to modules within your monolith? You can generate API docs, you can version interfaces, you can make completely new versions, etc.&lt;p&gt;I just feel like this would be a huge improvement:&lt;p&gt;- It&amp;#x27;s so much more engineering work to build the service handler scaffolding (validation, serialization&amp;#x2F;deserialization, defining errors)&lt;p&gt;- You avoid the runtime overhead of serialiation&amp;#x2F;deserialization and network latency&lt;p&gt;- You don&amp;#x27;t need to build SDKs&amp;#x2F;generate protobufs&amp;#x2F;generate clients&amp;#x2F;etc.&lt;p&gt;- You never have the problem of &amp;quot;is anyone using this service?&amp;quot; because you can use code coverage tools&lt;p&gt;- Deployment is much, much simpler&lt;p&gt;- You never have the problem of &amp;quot;we have to support this old--sometimes broken--functionality because this old service we can&amp;#x27;t modify depends on it&amp;quot;. This is a really undersold point: maybe it&amp;#x27;s true that microservice architectures let engineers &lt;i&gt;build&lt;/i&gt; things without regard for other teams, but they can&amp;#x27;t &lt;i&gt;remove&lt;/i&gt; things without regard for other teams, and this dynamic is like a no limit credit card for tech debt. Do you keep that service around as it slowly accretes more and more code it can&amp;#x27;t delete? Do you fork a new service w&amp;#x2F;o the legacy code and watch your fleet of microservices grow ever larger?&lt;p&gt;- You never have the problem of &amp;quot;how do we update the version of Node on 50 microservices?&amp;quot;</text></item><item><author>scient</author><text>Services, or even microservices, are more of a strategy to allow teams to scale than services or products to scale. I think thats one of the biggest misconceptions for engineers. On the other end you have the monorepo crew, who are doing it for the same reasons.&lt;p&gt;On your note about resiliency and scale - its always a waste of money until shit hits the fan. Then you really pay for it.</text></item><item><author>from-nibly</author><text>This is what I tell engineers. Microservices aren&amp;#x27;t a performance strategy. They are a POTENTIAL cost saving strategy against performance. And an engineering coordination strategy.&lt;p&gt;Theoretically If you have a monolith that can be scaled horizontally there isn&amp;#x27;t any difference between having 10 replicas of your monolith and having 5 replicas of two microservices with the same codebase. UNLESS you are trying to underscale part of your functionality.  You can&amp;#x27;t underscale part of your app with a monolith. Your pipe has to be big enough for all of it. Generally speaking though if you are talking about 10 replicas of something there&amp;#x27;s very little money to be saved anywhere.&lt;p&gt;Even then though the cost savings only start at large scales. You need to have a minimum of 3 replicas for resiliency. If those 3 replicas are too big for your scale then you are just wasting money.&lt;p&gt;The place where I see any real world benefit for most companies is just engineering coordination. With a single repo for a monolith I can make 1 team own that repo and tell them it&amp;#x27;s their responsibility to keep it clean. In a shared monolith however 0 people own it because everyone owns it and the repo becomes a disaster faster than you can say &amp;quot;we need enterprise caching&amp;quot;.</text></item></parent_chain><comment><author>gmfawcett</author><text>&amp;gt; does not require the strict discipline required in a monolith&lt;p&gt;How so? If your microservices are in a monorepo, one dev can spread joy and disaster across the whole ecosystem. On the other hand, if your monolith is broken into libraries, each one in its own repo, a developer can only influence their part of the larger solution. Arguably, system modularity has little to do with the architecture, and much to do with access controls on the repositories and pipelines.</text></comment>