विठ्ठलमाऊलीज्ञानेश्वरतुकारामपांडुरंगहरिएकनाथनामदेवरामकृष्णसोपानमुक्ताबाईचोखामेळाजनाबाईगोरा कुंभारॐ
← मुखपृष्ठ॥ श्री ॥№ 045

The Monolith Never Actually Left

Microservices did not remove coupling; they moved it somewhere harder to debug.


The hook

Last October, one of our services deployed a schema change at 4pm on a Tuesday. Three downstream services broke by 4:07. The on-call engineer opened Jaeger, traced the failure across four services, two queues, and a shared Protobuf definition, and said what I was already thinking: "This is just a monolith with network hops."


दुजे खंडे तरी · Even If the Other Breaks Away

दुजे खंडे तरी । उरला तो अवघा हरी ॥
देह आदि काय खरा । देहसंबंध पसारा ॥
तुका करी जागा । नको वासपूं वाउगा ॥
When you break a whole into parts, the whole does not vanish; it hides inside every part. Separating is not the same as separating from.


What I keep seeing

The Amazon Prime Video case study from 2023 made the rounds in every engineering Slack I am part of. Their video quality monitoring pipeline was a set of microservices orchestrated by AWS Step Functions: media conversion, defect detection, notification, all talking over S3 and queues. It worked. It also cost a fortune. They moved the whole thing into a single process and cut infrastructure cost by 90%.

The microservices camp reacted on cue. "That was not real microservices." "Wrong decomposition boundaries." "That is a pipeline, not a service." All possibly true. All beside the point. Smart engineers followed the prevailing orthodoxy and ended up with a system that was more expensive, harder to debug, and slower to change than a single deployable unit.

They are not alone. Segment moved back from microservices in 2018. Kelsey Hightower, one of Kubernetes' most prominent advocates, said most companies would be better off with a monolith and a good deployment pipeline. I have been guilty of the opposite advice myself, early in my career, which is how I know the orthodoxy is seductive.

The mechanics

When you decompose a monolith into microservices, you trade function calls for network calls. A function call takes nanoseconds and cannot fail due to DNS resolution, TLS handshake, load balancer routing, or network partition. A network call can fail in all of those ways, plus timeout, plus retry storm, plus partial failure where the request succeeds but the response is lost.

Every service boundary requires you to solve serialization (Protobuf, JSON, Avro), service discovery (Consul, DNS, Kubernetes service objects), load balancing, circuit breaking (Resilience4j, Envoy), distributed tracing (OpenTelemetry), and schema evolution (backward-compatible Protobuf changes, contract testing with Pact). These are real engineering costs. They are justified when you genuinely need independent deployment, independent scaling, or organizational autonomy across team boundaries. For most systems, you do not.

The coupling does not disappear when you draw service boundaries. If Service A needs data from Service B to fulfill a request, that is coupling. You have not eliminated it. You have made it slower, less reliable, and harder to trace. You turned a stack trace into a distributed treasure hunt.

Where Tuka comes in

Tukaram's verse is ontological. दुजे खंडे तरी, उरला तो अवघा हरी: even if the other breaks away, what remains is still the whole. The act of splitting does not create independence. It creates the illusion of independence while the underlying unity persists, now hidden.

This is the microservices trap precisely. You split the monolith. You deploy 47 services. You feel autonomous. Then one service deploys a schema change and three downstream services break at 2am, and you realize that नको वासपूं वाउगा: do not needlessly spread out. The spreading is not growth. It is diffusion.

What I would actually do

Start every new project as a modular monolith. One deployable unit, strict module boundaries enforced by ArchUnit or similar static analysis, clear interfaces between modules that could become service boundaries later. The decision to extract a service should require evidence, not architecture diagrams. Evidence means: this module needs to scale independently (proven by load data), this module is owned by a separate team with a different release cadence (proven by git history), or this module has a fundamentally different availability requirement (proven by SLO data). Without that evidence, the module stays in the monolith. Your distributed-systems tax is zero until the day you actually need to pay it.

Chetan Dhandal

RytkpyRkhq
← Previousक्षमेची तू मूर्ती
Next →विष्णुमय जग वैष्णवांचा धर्म