Software Architecture Is All About Trade-Offs

There is no best architecture, there is what you get and what you pay. Every decision gives you something and takes something away, if you only see what it gives, you have not understood the decision yet.

The Idea Nothing is free

Decision You get You pay
Microservices Parts that deploy and scale on their own A network in the middle of every call
Message queue Parts that do not wait for each other Duplicates, and the data that is correct later
Cache Fast reads Stale data
Second database Reads that do not slow down writes Two copies that have to agree

Architecture is not picking a "good" solutions = there are no "good" solutions, only "paid" ones, architecture is choosing which bill you pay.

The Catch You pay now, you get it later

The "price" starts on day one, the benefit starts when the need shows up, if the need never shows up, you "paid" for nothing.

That is all over-engineering is, nobody picked bad technology, they "paid" for a problem they did not have.

The opposite mistake costs the same, a system with no boundaries chose "fast today" and pays the bill with every change after that. Too much architecture and too little are one mistake = nobody looked at the price.

The Trap Logical is not physical

A team has a tangled monolith, it needs less coupling, it "buys" microservices.

One place order request entering the Sales service and hopping over HTTP to Pricing, Warehouse and Billing, each its own deployment. A ledger under the drawing: needed less coupling, received the same calls and dependencies, paid a timeout, a retry, a version and a deploy order on every hop.
This is an example of the bad trade
Needed: less coupling
Received: the same calls between the same parts
Paid: a network on every one of them

Sales still calls Pricing. Warehouse still calls Billing. The coupling did not move plus now there is a network in the middle of it. The team "paid" the full price and got nothing it wanted.

Coupling is a logical problem: who knows what about whom, Microservices are a physical decision: what runs where. You cannot fix the first by changing the second.

Moving code to another server changes where it runs. It does not change what it depends on.

The Way Out "Pay" when the need is real

Fix coupling where it lives, draw the boundaries inside one process = every module owns its data, and modules talk through contracts. That costs discipline, not infrastructure, that's what a loosely coupled monolith is about.

Now the physical decision can wait, the day when one module has to scale or ship alone, move that one out.

The Rule Know the price

Every decision has a price, if you cannot say what it is, you are not ready to decide.

Two questions before you add anything: what do we get, and what do we pay? The first one is easy, everybody knows what microservices give you, the architect is the one who knows the second.


More posts
← All posts  ·  RSS © 2026 DotNET Leet