Nguyen Le PhongNguyen Le Phong

软件架构基础第 1 篇,共 12 篇

The True Cost of Microservices

Microservices can create real team autonomy, but they also move cost into operations, data consistency, observability, testing, and coordination. A calm reflection on when that cost is worth paying and when a modular monolith is the kinder architecture.

The coffee machine in the office used to be the quietest place to hear architecture decisions become real. Someone would stand there with a paper cup, waiting for a slow stream of coffee, and say something like: the checkout team is blocked again because the catalog team is not ready to release. A week later, the word microservices would appear in a planning document, not as a technology choice yet, but as a hope that teams could finally stop waiting for each other.

That hope is understandable. A growing monolith can feel heavy. One deployment pipeline serves every team. One shared database becomes the place where every shortcut and emergency fix settles. A small change in billing can create fear in onboarding. Meetings become less about product decisions and more about finding a release window that does not hurt anyone too much. When people say they want microservices, they are often asking for something very human: room to move.

The difficult part is that microservices rarely remove complexity. They relocate it. The code may become smaller inside each service, but the system becomes larger between services. A function call becomes a network call. A transaction becomes a saga or an eventually consistent workflow. A local stack trace becomes a trace across five services, three queues, and two dashboards. The cost does not disappear just because the repository looks cleaner.

The first cost is operational. Every service needs a build, deployment, configuration, secret management, health check, alert, log stream, dashboard, rollback path, and owner. One service is manageable. Ten services require discipline. Fifty services require a platform. Without that platform, engineers spend less time improving the product and more time remembering which service owns which failure mode. Microservices ask the organization to become good at operations before the architecture can feel light.

The second cost is data. In a monolith, consistency is often boring in the best possible way. A database transaction can update related records together, and the code can rely on that boundary. In microservices, each service should own its own data, which means the system must accept delay, duplication, and repair. An order may be created before the invoice is visible. A payment may succeed while the notification service is down. These are solvable problems, but they are not free problems. They require careful event design, idempotency, reconciliation, and product language that helps people understand temporary states.

The third cost is observability. When a user says the page is slow, the answer is no longer in one log file. It may sit inside a chain: API gateway, auth service, order service, inventory service, payment service, message broker, email worker. To debug that without guesswork, the team needs trace IDs, structured logs, metrics, SLOs, and enough shared practice to read them under pressure. Observability is not decoration for microservices. It is part of the architecture.

The fourth cost is testing. Unit tests remain useful, but many important failures live at the boundary between services: a changed API contract, a missing event field, a timeout that only appears when a downstream dependency is slow. Teams need contract tests, integration environments, realistic fixtures, and a habit of thinking about failure paths. Otherwise the system only works when every service behaves politely, which is not a reliable assumption.

The fifth cost is coordination, even though coordination is the thing microservices are supposed to reduce. Teams can deploy independently only when their contracts are stable, their ownership is clear, and their dependencies are honest. If every service still needs three other teams to release first, the organization has not escaped the monolith. It has built a distributed version of the same waiting room.

This is why the most useful question is not, should we use microservices? A better question is, which cost are we already paying, and which cost are we ready to pay next? A modular monolith may be the wiser answer for a long time. It can give teams clearer boundaries, better ownership, and cleaner code without forcing every product change to cross the network. Sometimes the kindest architecture is the one that keeps simple things simple while preparing clean seams for the day extraction becomes necessary.

Microservices begin to make more sense when the pain is no longer theoretical. Teams are blocked by shared deployments every week. Some domains need independent scaling. Failures should be isolated because one part of the product is much riskier or much busier than the rest. The organization has enough engineering maturity to own pipelines, observability, incident response, and service contracts. At that point, microservices can be a good trade, not because they are modern, but because they match the shape of the work.

I have seen teams become calmer after extracting the right service. The deploy became smaller. The owner became clearer. The dashboard finally showed one team the health of the thing they were responsible for. I have also seen teams become slower after extracting too early. Every feature needed choreography. Every local setup became fragile. Every bug became a small investigation across services that nobody fully owned. The difference was not the architecture diagram. It was whether the team had enough reason and enough practice to pay the bill.

The true cost of microservices is not only cloud spend, Kubernetes YAML, or extra repositories. It is the attention required to keep a distributed system understandable. It is the discipline to make contracts explicit, failure visible, data repairable, and ownership real. If your team is ready to pay that cost, microservices can create meaningful freedom. If not, there is no shame in staying with a well-kept modular monolith a little longer. Good architecture is not the one that sounds advanced in a meeting. It is the one your team can operate, explain, and improve on an ordinary Tuesday afternoon.

If you have lived through a microservices migration, I would be curious where the cost showed up first for your team: deployment, data, debugging, testing, or the quieter coordination work around all of them.

你觉得这篇文章如何?