
Service Boundaries Drawn on an Org Chart Will Not Survive Contact With the Data
Team names make convenient service names and terrible service boundaries. The real seams are visible in your write patterns and your transaction logs, not in the reporting structure.
The first decomposition diagram in most microservices programmes is a redrawn org chart. Billing team gets a billing service, catalogue team gets a catalogue service, the growth squad gets something called Growth. It is a fast way to get agreement in a room, and that is exactly the problem. Nobody in that room is arguing, because nobody has yet looked at which tables get written together inside a single transaction.
Conway's law is usually quoted as a reason to align services with teams. It is more accurate as a warning. It says your architecture will resemble your communication structure whether or not that structure describes your data. If the reporting lines happen to match the write patterns, you get a clean split. If they do not, you get services that cannot complete an operation without three network calls and a compensating transaction, and the team that owns each one will insist the coupling belongs to somebody else.
The org chart describes people, not consistency requirements
A service boundary is a consistency boundary before it is anything else. Inside it, you can use a database transaction and get atomicity for free. Across it, you cannot, and every write that spans the line has to be rebuilt as a saga, an outbox, a retry policy, and a reconciliation job for when it half-fails at three in the morning.
Org charts encode none of that. They encode budget, hiring history, and whoever happened to be available when a project started. A payments team might own card capture and refunds while a separate operations team owns the order state that both of those mutate. On the chart those are two clean boxes. In the database they are one transaction that updates order status, ledger entry, and reservation together, and splitting it converts a five millisecond commit into a distributed workflow with four failure states.
The tell is easy to look for and almost nobody looks: pull the set of tables written inside each transaction in your busiest code paths. Tables that are consistently written together belong on the same side of a boundary. That single query tends to contradict a good portion of the proposed decomposition, which is why the guide on how to find service boundaries using data and transaction patterns starts there rather than with domain workshops.
Entities that appear everywhere are not shared, they are misnamed
The second failure is the god entity. Customer, Order, Product. Every proposed service claims to need it, so the design either duplicates it everywhere or creates a Customer Service that becomes a synchronous dependency on the critical path of every request in the system.
Usually the entity is a naming collision rather than a genuinely shared object. The customer that billing cares about is a payment method, a tax jurisdiction, and a credit position. The customer that support cares about is a contact history and an entitlement. The customer that the recommendation system cares about is a behaviour vector. These share an identifier and almost no fields. Modelled as one entity, they force every team through a single schema and a single deployment. Modelled as three local views keyed on a shared customer ID, they decouple cleanly and the only thing crossing the boundary is that identifier plus a small number of events.
The heuristic that holds up: if two teams want different fields on the same noun and change them on different schedules, it is two entities wearing one name.
What the two designs actually cost you
| Decision point | Boundary from the org chart | Boundary from the data |
|---|---|---|
| Common write path | Spans two or three services | Contained in one transaction |
| Failure handling | Saga plus compensations plus reconciliation | Database rollback |
| Typical change | Coordinated release across teams | Single deploy |
| Shared entity | One canonical service on the hot path | Local views on a shared ID |
| Query for a screen | Fan-out and join in the client or a gateway | One query, maybe one call |
| What breaks first | Latency and partial writes under load | Team ownership arguments |
The right column is not free. It sometimes puts two teams inside one service, which is politically harder and operationally simpler. That trade is worth making, because deployment coordination between two teams is a scheduling problem while a distributed write across two services is an engineering problem that never fully goes away.
Where the org chart legitimately wins
There is a real case for team-aligned boundaries, and it is worth stating so this does not read as an absolute. Where the data genuinely is separable, aligning the service to the team that owns the domain reduces handoffs and gives you an on-call owner who understands the code. Notification delivery, document generation, search indexing, anything that consumes events and owns no authoritative state, splits cleanly along whatever line you like. These are the boundaries to cut first, and they are also the ones that give the misleading impression that decomposition is easy.
The distinction is authority over state. If a service is the only writer of its data, team alignment is a bonus. If two services both need to write the same fact atomically, the org chart lost the argument before it started, and the choice of synchronous calls versus events between services becomes the thing you spend the next year arguing about instead.
Five things to do before drawing the diagram
- Extract the set of tables written together per transaction across your top twenty endpoints by traffic. Cluster them. Those clusters are candidate boundaries.
- List every foreign key that crosses a proposed boundary. Each one is either a saga you will build or a boundary in the wrong place.
- For each shared entity, ask each team which fields they read and which they write. Non-overlapping field sets mean separate entities.
- Find the queries that would need a join across the new line. Decide now whether they become a read model, a projection, or an accepted fan-out.
- Take the three highest-traffic write paths and write out the failure states if they become distributed. If nobody wants to own the reconciliation job, do not cut there.
None of this requires committing to a split. It is analysis you can do against the system you already have, and it is the cheapest work in the whole programme.
What to do next
Run the transaction clustering before the next architecture workshop and bring the output to it. If the clusters contradict the proposed service map, the map changes, not the data. In many cases the honest conclusion is that the seams are not clean anywhere yet, which is an argument for enforcing module boundaries in the existing codebase first and revisiting the split later, and the guide covering the situations where microservices are the wrong choice is the fastest way to test whether that applies to you.
If the analysis says the seams are real and you want a second read on the decomposition before committing engineering time, our microservices architecture practice works from the transaction and query patterns rather than the reporting structure.
Fastnexa Engineering
Software Development Team at Fastnexa. We write from real client work, and we are happy to talk through yours.
Ready to ship this?
Bring this problem to a free 30-minute call with the team that wrote the post.
Book a demoMore from the blog
View all
Observability Is a Prerequisite for Splitting a Monolith, Not a Follow-Up Task
Almost every migration schedules tracing after the first services ship. That ordering removes the stack trace before anything replaces it, and it hides the data you needed to choose the boundaries.

The Take-Home Test Filters for Free Time, Not Engineering Ability
Take-home exercises select the candidates with the most spare evenings and the least verification, and the alternative costs an hour of an engineer's time rather than eight of a candidate's.

The Modular Monolith Is Not a Compromise, It Is Usually the Correct Answer
A modular monolith gives you enforced boundaries, independent modules and a single transaction. Microservices give you the same boundaries plus a network, and the network is the part that costs you.
Related services
Want help putting this into practice? Here is how we deliver it.