In large organizations, integration often starts with a sentence that sounds completely harmless: "We just need to pass a few fields from system A to system B." On the diagram, one arrow appears. Technically, it looks like a small piece of work: an API, an event, maybe a simple batch. A few days or a sprint, and the problem should be solved.
The problem is that the arrow rarely stays just an arrow. Behind it come data contracts, mapping, authorization, monitoring, retries, error handling, versioning, testing, deployment, alerts and ownership. Someone has to decide what happens when the system on the other side is unavailable, when the data is incomplete, or when one application changes its model before the other one does. A few years later, someone looks at the architecture and asks: why are these two systems talking to each other at all? And sometimes nobody remembers.
An Integration Is A Dependency
For a long time, I looked at integrations mainly as a technical problem. We have two systems, data needs to move between them, so we design a way to exchange it. Today, I look at it a little differently.
Every integration creates a dependency between two areas that, from that point forward, need to know about each other. A change on one side can affect the other. A failure in one system can stop a process in another. Someone has to monitor, maintain and understand that dependency.
An integration is not just a connection between two systems. It is a promise that they will continue to understand each other for years to come.
That is why, before designing an API, I increasingly want to ask an earlier question: why do these systems need to integrate at all?
Who Really Owns The Data?
One of the most common problems begins when the same information starts living in several places. CRM has the customer's address. Billing needs the address too. Customer service wants its own copy. The marketing platform needs it as well.
The natural answer is synchronization. The address changes in one system, so the others are informed. Events appear, queues appear, retry mechanisms and reconciliation jobs appear. But sometimes the real question is not: "How do we synchronize the address better?"
The real question is: which system actually owns the customer's address?
If we cannot answer that, even the best integration will not solve the problem. We will simply become more efficient at synchronizing unclear responsibility. And when two systems eventually disagree, someone will still have to decide which one to trust.
That is no longer an API problem. It is an ownership problem.
Sometimes We Integrate An Exception We Should Not Have
Another common case appears when a business process does not fit the main model. One product works differently. One country needs a special flow. One old customer still has conditions that nobody new receives anymore. The easiest response is often to add another integration or another exception to an existing one.
Technically, this is often possible. But after a few years, the system can end up supporting dozens of historical cases because every time it was easier to build another flow than to make a business decision to stop supporting one.
In those situations, before asking "how do we support this exception?" it can be worth asking: do we still want to support it at all?
That may be a much harder conversation than designing an integration. It requires a product or business decision, not just technical work. But one such decision can remove more complexity than months of refactoring.
Do Not Copy Data Just Because You Can
There is another pattern I see often. A system needs a few pieces of information, so instead of reading them from the source when needed, we create a local copy.
At first, it looks convenient. The system becomes more independent and does not need to call the source every time. The problems come later: who updates the copy, how quickly, what happens when an event is lost, what happens when one system has value A and another has value B, and what happens when the customer changes the same information twice in a short period of time?
Once again, we start building additional mechanisms to fix a problem created by an earlier architectural decision.
I am not saying that copying data is always wrong. Sometimes it is exactly what we need for performance, availability or the nature of the architecture. But it should be a conscious choice, not the default response to: "this system needs the data too."
Arrows On Diagrams Are Cheap
This is one of the most misleading things about architecture. On a diagram, an integration costs one arrow. You can draw ten of them in a few minutes.
In a real system, every one of those arrows has a lifecycle. Someone has to build it, test it, monitor it and maintain it. Someone needs to receive an alert when it stops working. Someone needs to know whether to retry a message or reject it. Someone has to update the contract when the product changes.
And if the systems belong to different teams, the integration also creates an organizational dependency. A change that one team could make tomorrow may suddenly require synchronization with another team's roadmap.
That is why the number of integrations affects more than architecture. It affects the speed of the organization too.
Middleware Will Not Fix Ownership
I work a lot with integration platforms, and I still believe good middleware is extremely valuable. It can standardize communication, isolate systems, handle failures and make a complex landscape much easier to maintain.
What it cannot answer is: who should own this process?
If the organization cannot decide where a particular piece of logic should live, it becomes very easy to place it "in between." Some logic stays in CRM, some in billing, some in middleware. Eventually, nobody owns the whole behavior, while three teams own fragments of it.
Technically, everything is connected. Organizationally, nothing is really owned end-to-end. And in that situation, another integration can actually make things worse.
Sometimes The Best Architectural Decision Is Not Technical
This is probably one of the most important things I have learned from working with large systems. Some of the best architectural simplifications begin with a business decision.
We can stop supporting an old product variant. We can define a single source of truth. We can move responsibility for the entire process into one system. We can change the process so another system no longer needs data that we were previously copying. Sometimes we can even accept a small amount of manual work for a very rare case instead of building and maintaining an automated integration for the next ten years.
At first, that may look less "technical" than designing a new API. But it may remove the need for the API completely.
This Is Not About Avoiding Integrations
Of course, large organizations cannot operate without integrations. Systems have different responsibilities and they need to exchange data. A modern architecture will contain many such connections.
The goal is not to minimize the number of integrations at any cost. The goal is to make sure every integration has a good reason to exist.
I want to know why data needs to move from one system to another, who owns it, what happens if the transfer fails, and whether the process really needs that dependency. If we can answer those questions clearly, then build the integration.
If we cannot, we may have started designing the solution too early.
Final Thoughts
I used to start integration discussions with: how do we connect these systems? Today, I increasingly want to start one step earlier: why do they need to be connected at all?
Sometimes the answer will be an API, an event, a queue or middleware. But sometimes the answer will be a process change, a single owner for the data, or a simple decision that a historical exception is no longer worth supporting.
And that is when the best integration may turn out to be the one we never had to build.
Before designing the interface, question the dependency.