惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

F
Full Disclosure
WordPress大学
WordPress大学
小众软件
小众软件
Cloudbric
Cloudbric
AWS News Blog
AWS News Blog
腾讯CDC
量子位
人人都是产品经理
人人都是产品经理
大猫的无限游戏
大猫的无限游戏
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
V
Vulnerabilities – Threatpost
Scott Helme
Scott Helme
Hugging Face - Blog
Hugging Face - Blog
博客园_首页
C
CXSECURITY Database RSS Feed - CXSecurity.com
The Hacker News
The Hacker News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
IT之家
IT之家
Jina AI
Jina AI
Attack and Defense Labs
Attack and Defense Labs
S
SegmentFault 最新的问题
Simon Willison's Weblog
Simon Willison's Weblog
The Cloudflare Blog
阮一峰的网络日志
阮一峰的网络日志
T
Tailwind CSS Blog
Last Week in AI
Last Week in AI
博客园 - 【当耐特】
Google Online Security Blog
Google Online Security Blog
美团技术团队
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
V
Visual Studio Blog
罗磊的独立博客
L
LINUX DO - 最新话题
博客园 - Franky
博客园 - 叶小钗
Apple Machine Learning Research
Apple Machine Learning Research
The Last Watchdog
The Last Watchdog
J
Java Code Geeks
AI
AI
C
Cisco Blogs
酷 壳 – CoolShell
酷 壳 – CoolShell
C
Cyber Attacks, Cyber Crime and Cyber Security
Cisco Talos Blog
Cisco Talos Blog
博客园 - 三生石上(FineUI控件)
雷峰网
雷峰网
Help Net Security
Help Net Security
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
云风的 BLOG
云风的 BLOG
I
Intezer
S
Securelist

Arpit Bhayani

Temporal Primer - Building Long-Running Systems What Matters in Production RAG Structure of Every LLM Chat How LLMs Really Work Databases Were Not Designed For This BM25 JOIN Algorithms Venting at Work Comes at a Reputation Cost Why Half Your Skills Expire Every Few Years Multi-Paxos - Consensus in Distributed Databases MySQL Replication Internals Bloom Filters When You Increase Kafka Partitions Product Quantization The Q, K, V Matrices The Day I Accidentally Deleted Production How LLM Inference Works What are Blocking Queues and Why We Need Them Heartbeats in Distributed Systems How Writes Work in Apache Cassandra Redis Replication Internals How to Handle Arrogant Colleagues at Work How Does a CDN Handle Content Replication You Can't Fix Everything on Day One When Emotions Spill Over at Work Why gRPC Uses HTTP2 Meetings With No Agenda Are a Waste of Time Career Longevity Beats Constant Job Hopping Stay Relevant at Higher Salary Levels Why Distributed Systems Need Consensus Algorithms Like Raft Why Do Databases Deadlock and How Do They Resolve It Why and How Cache Locality Can Make Your Code Faster Why Eventual Consistency is Preferred in Distributed Systems Why does DNS use both UDP and TCP Should You Do a Master's My Honest Take Empathy Makes Great Engineers Unstoppable Good Mentors Build People, Not Just Skills Why You Should Always Have Back-Burner Projects Before You Push Back, Know What You're Standing On Be the One They Can Count On How Much Are People Willing to Bet on You How to Get Leadership to Say Yes to Your Project Don't Let Your Best Ideas Die in Silence Be the Person Everyone Wants to Work With The XY Problem and How to Avoid It The Startup Hiring Lie Nobody Talks About You Won't Be Promoted Unless You Ask It's Not Enough to be Right; Learn to be Heard No One Ships Great Software Alone You Don't Win by Proving Others Wrong Appreciate Generously; It Costs Nothing, But Builds Everything Your Soft Skills Aren't Soft at All Before you form an opinion, experience it Why You Need Both Curiosity and Action to Thrive A Daily Worklog Changed Everything How We Handle Mistakes Defines Us Own Your Mistakes Don't Wait. Step Up. Temporary Fixes Are Permanent Why Interviews Are Biased And What Sets You Apart Saying 'This isn't my problem' is actually the problem How to Write Effective OKRs Never Lose a Battle due to Miscommunication When In Doubt, Code It Out How to Follow Up Without Annoying People Lead Projects That Land, Execution Over Everything Abstract Thinking Will Define Your Next Decade We Engineers Suck at Task Estimation Shiny Obect Syndrome in Tech When to Change Jobs - The 3P Framework Comfort and Competition - Know When to Switch Gears Paper Notes - On-demand Container Loading in AWS Lambda Paper Notes - SQL Has Problems. We Can Fix Them Pipe Syntax In SQL Paper Notes - NanoLog - A Nanosecond Scale Logging System Don't Wait, Learn - The Best Resource is Mythical Paper Notes - WTF - The Who to Follow Service at Twitter The Unexpected Benefit of Reading Random Engineering Articles Roadmaps Are Limiting Your Growth Stop Leaving Money on the Table - Negotiate Your Job Offer Never Bad-Mouth Your Past Employers Show You're a Culture Fit Quantify your resume, Know Your Numbers The Importance of Being Likeable in Interviews Questions to Ask Your Interviewer How to Build Trust Through Collaboration Do This, Once You Are Out of the Interview Cycle Stop Pitching Ideas, Start Pitching Projects Read Those Design Docs, Even the Ones That Seem Irrelevant The Best Engineering Lessons Happen During Outages Great Engineers Start Broad LLM Summaries are Ruining Your Learning Turn System Design Interviews into Discussions Title Inflation At Work, Find Your Own Projects 6 Simple Strategies to Cracking Any Tech Interview How to Remain Unblocked Solving the Knapsack Problem with Evolutionary Algorithms Generating Pseudorandom Numbers with LFSR Local vs Global Indexes in Partitioned Databases Partitioning Data - Range, Hash, and When to Use Them
Your Monolith Is Already A Distributed System
Arpit Bhayani · 2026-04-28 · via Arpit Bhayani

You have a monolith, and you are proud of it. One repo, one deployment, one database - no Kubernetes, no service mesh. You have watched teams burn months “extracting microservices” and come out slower than when they started. You stayed sensible. You kept the monolith.

Here is the uncomfortable part - your monolith may already be a distributed system. Not in the infrastructure sense but in the only sense that actually matters: coupling, contracts, failure modes, and coordination overhead. You are paying the price of distribution without any of the benefits. Let me explain…

Database Is A Global Variable

The most dangerous coupling in any large monolith is not in the code. It is in the database.

A shared relational database behaves like a global variable at the scale of the entire system. Any module can read any table. Any migration could touch any data and schema. Any schema change is, in effect, a broadcast to every part of the system that has ever issued a query against that table.

Think about what happens when you rename a column in your orders table.

You search the codebase for references. You find the obvious ones – the OrderRepository, the OrderService, and the admin panel query. You miss the subtle ones: the analytics module that pulls orders directly to avoid going through the service layer.

Distributed systems fail when Service A changes its contract, and Service B breaks silently at runtime. The monolith has the same failure mode. The only difference is that in a distributed system, the contract is an API schema. In the monolith, the contract is the database schema – and it is implicit, unversioned, and invisible.

-- "Safe" schema change in a monolith
ALTER TABLE orders RENAME COLUMN customer_id TO user_id;

-- This breaks the report scheduler that runs at 2am,
-- which you will find out about at 9am.

If your monolith has a single database and more than three or four distinct feature areas, your database schema is already acting as a distributed coordination point. It is the pub/sub bus you never intended to build.

Modules Are Services

At some point in the life of every growing monolith, someone draws a diagram. Boxes and arrows. UserModule calls OrderModule, which calls PaymentModule, which calls NotificationModule. The diagram looks clean. The team feels good about the architecture.

The problem is that those boxes are not enforced by anything. There is no compilation boundary between them. There is no ownership model. There is no contract that governs what OrderModule is allowed to ask of PaymentModule. The arrows on the diagram are “aspirational”.

In practice, the UserModule calls the PaymentModule directly because the person who needed that data was under a deadline, and the indirection through OrderModule seemed unnecessary. The NotificationModule pulls from the users table directly because it needed a field that was not on the API that the UserModule exposed. The diagram no longer matches the code, and nobody is sure which is wrong.

This is temporal coupling. This is domain coupling. These are the exact failure modes that distributed systems architects spend careers trying to design around, and they are sitting inside your monolith right now.

When you finally decide to extract any one of those modules – and at some point you will – you will discover that it has invisible coupling going through the entire codebase.

Synchronous Chains

A function call inside a monolith takes nanoseconds. This makes it feel free. Teams develop a habit of composing functionality through long synchronous chains because there is no visible cost: no network latency, no retries, no circuit breakers. The call stack grows deeper every quarter.

def process_checkout(cart_id):
    cart = cart_service.get(cart_id)
    user = user_service.get(cart.user_id)
    inventory = inventory_service.check(cart.items)
    payment = payment_service.charge(user, cart.total)
    order = order_service.create(cart, payment)
    notification_service.send_confirmation(user, order)
    analytics_service.track_conversion(user, order)
    return order

This reads cleanly. Every step is obvious. Every step is also synchronous, and every step must succeed for the operation to complete. Interestingly, the failure domain of this function is the union of the failure domains of every system it touches.

Your monolith has the coordination costs of a distributed system. It has just traded visible network calls for invisible function call chains and made the failure modes harder to reason about in the process. Imagine any of the above functions in the chain running slower or erroring out.

Microservices teams discover early that shared code is coupling in disguise. If Service A and Service B both depend on payments-client@v1.2.3, then upgrading that library is no longer a local decision. You are coordinating a deployment across service boundaries.

Monoliths have the same problem, and it is often worse because there is no version number to make the coupling visible.

The BaseRepository that every module extends. The ApplicationContext singleton that holds global configuration. The EventEmitter that any part of the codebase can subscribe to or emit on. These are the shared libraries of the monolith, and they are the reason that a change to a “utility” class causes five unrelated test suites to fail.

Single Deploy Is An Illusion

Teams love citing the monolith’s single deployable artifact as a virtue, and in many ways it is. But it is also a hidden cost that scales with team size.

A single deploy means that every team’s changes land at the same time. This sounds like coordination, because it is. As the team grows, the deploy becomes a ritual: a changelog spanning twenty pull requests, a QA pass that blocks on the slowest team, a rollback that takes down features that were working fine because they shared the deploy unit with the thing that broke.

Distributed systems have the same problem when services are tightly coupled. The monolith has spent decades developing patterns to escape issues like semantic versioning, feature flags, backward-compatible migrations, and canary deployments, and hence, single deploy feels so much simpler on paper.

What Your Monolith Has Actually Become

If your monolith is more than a few years old and more than a few engineers have worked on it, do a quick audit:

  • How many distinct feature areas are read from the same database tables?
  • Can you draw the actual call graph between your “modules” – not the intended one, the real one?
  • How many synchronous chains touch more than four distinct concerns?
  • How many engineers need to coordinate on a deployment?
  • When was the last time a change to a “utility” or “shared” class caused unexpected breakage somewhere else?

If the answers to these questions are not small, you already have a distributed system. The difference is that microservices teams know they have one, and yours is invisible.

The invisible distributed system is worse.

Not An Argument for Microservices

By the way, none of this is an argument for splitting your monolith. That is a separate conversation, and for most teams, the answer is probably no.

The argument is narrower: if you are going to keep the monolith, keep it well.

  • Define real boundaries inside it.
  • Own the data per module – one module should write to a set of tables, and other modules should go through its interface to read them, not the table directly.
  • Make the synchronous chains visible, and
  • Consciously decide which parts could be async.

Treat shared utilities with the same care you would treat a shared library in a distributed system, because that is what they are.

A well-structured monolith is one of the best architectures you can have. It gives you the deployment simplicity and the refactoring confidence that distributed systems genuinely cannot. The compiler catches your mistakes. Latency is in nanoseconds. There are no distributed transactions to debug.

But a poorly-structured monolith is not a monolith at all. It is a distributed system with the network calls replaced by function calls and the explicit contracts replaced by implicit database coupling.

The pride is understandable. The architecture might not deserve it yet.