A bug ticket has been open for nine days. Three engineers have looked at it. Each one has a different view of what the function is supposed to return when the upstream service responds with null. None of them are wrong. The code is consistent with all three readings. The diagram does not specify. The interface document — written eighteen months ago — predates two of them. This is not a code bug. It is interface ambiguity surfacing the only way it can: under load, during integration, when somebody actually has to commit to a definition of correct behaviour.
An interface is not a function signature.
It is a contract about behaviour, ownership, and consequence.
01 An interface is a contract, not a wire
When teams say "we have the interface defined," they almost always mean: we have agreed on the data shape. The fields. The types. The function name. Maybe the protocol.
That is the easy part.
A real interface contract specifies six things, not one:
- Shape — what data flows in each direction.
- Ownership — which team is authoritative when the contract changes, and who reviews changes from the other side.
- Failure mode — what happens when the producer is unavailable, slow, or returns malformed data.
- Ordering and idempotency — whether two of the same call mean two of the same effect.
- Change protocol — how the contract evolves without breaking the other side.
- Evidence of conformance — how either side proves their implementation matches.
Most "interface specs" answer the first one comprehensively and leave the other five implicit. Implicit means: the people closest to the code know. The people who will inherit it do not. This is an SS — System Structure & Interfaces pattern. The boundary appears defined because the data shape is documented. The boundary is undefined because behaviour, ownership, and change governance are not.
An interface specced only at the data-shape level is a wire, not a contract. The five missing dimensions — ownership, failure mode, ordering, change protocol, evidence — are where integration risk concentrates and where late-cycle cost is paid.
02 Where ambiguity hides
Interface ambiguity rarely looks like ambiguity. It looks like everything is fine — until something has to change.
Three patterns concentrate the risk.
The boundary owned by "both teams." When two teams share an interface, "shared" usually decays into "neither." Each side assumes the other is the steward. Nobody is. The contract is still up there in Confluence; it has just stopped being maintained against reality.
The contract that lives only in code. The data shape is enforced by types or schemas. Behaviour, failure mode, and ordering are enforced by whoever wrote the implementation. There is no document. The original author has the model in their head. When that person rotates off the team, the model leaves with them — but the code keeps running, so nobody notices for months.
Contract drift. The interface document was correct on day one. The implementation has changed twelve times since. The document has not. Anyone reading it is reading a fiction. The signal that this has happened is rarely a bug — it is the slowness of new engineers asking "what does this actually do?"
Pick a boundary that two teams share. Ask each side independently: who is authoritative when the contract changes? If you get two different answers — or two versions of "the other team" — the boundary is unowned, and the next change to it is going to surface that fact at the worst possible moment.
03 Why it surfaces late and expensive
Single-team work tolerates interface ambiguity well. One engineer keeps the model in their head. Behaviour is consistent because the same person keeps writing both sides.
Integration is where the cost lands.
At integration, two implementations meet. Each one was internally consistent. The gap between them is invisible until somebody runs an end-to-end scenario and discovers that "correct" means something different on each side. By that point, the milestone is days away. Three teams are involved. Engineering management is asking why the demo is slipping. Bug triage cannot resolve, because the underlying question — what is this interface supposed to do? — does not have an authoritative answer anywhere outside the heads of two people who weren't in the room when it was designed.
This is the latency that makes interface ambiguity a silent killer. The ambiguity was there in week three. The cost did not appear until week eighteen. Nothing in the intervening fifteen weeks of green status reports flagged the problem, because no test could detect it. There was no failure to detect. There was a definition gap, and definition gaps do not show up in test reports. This is also where CR — Change/Risk Exposure compounds: every change to one side that does not trigger a contract update silently raises the integration risk for the other side, with no signal in the standard cadence.
When the only person who can authoritatively define an interface's behaviour is one engineer carrying the model in their head, the team has a hidden continuity risk. The interface still works — until that person rotates, takes leave, or is simply in a different meeting when the integration question lands.
04 What to check before your next milestone
The fix is not more documentation. It is structural ownership of the boundary, with evidence that the contract is being maintained. Pick the interface in your system that has caused the most recent triage pain, and spend ten minutes walking it.
A team that owns its boundaries can answer all five questions without reaching for the original author. The contract is current. Failure mode is documented. Ownership is named. New engineers become productive at the boundary from the artifacts alone — not from an oral history briefing.
Interface ambiguity is not a documentation problem. It is a structural ownership problem — and the cost is paid late, at integration, when two consistent implementations finally have to be reconciled. Teams that own their boundaries see the risk before it becomes a missed milestone.
If this pattern feels familiar, and the boundaries in your system depend more on individuals than on documented contracts, the useful next step is a structured read of where the exposure concentrates. The SYS Readiness Check covers all five dimensions: definition clarity, interfaces, validation readiness, change exposure, and execution control - It gives you a bounded diagnostic in under eight minutes.