Integration work is often judged by whether the first message arrives. That is the easy part. The harder question is what happens when a field changes, a partner goes offline, a message is delivered twice or the system that owns the data is replaced.

Integration contract with producer, consumer and failure path

An interface is not a contract

An endpoint, a payload schema and an authentication method describe how to call a system. They do not describe what the data means, who owns it, how long it is valid, what happens when it is rejected or how a change will be communicated.

A useful contract includes semantics, ownership, availability expectations, error behaviour, versioning and the process for change. Without those, the integration is a technical connection with an organisational assumption hidden inside it.

Design for failure before go-live

Distributed systems fail in ordinary ways: timeouts, duplicate delivery, out-of-order events, partial success and stale data. The integration should make those states visible and recoverable.

Idempotency, dead-letter handling, replay, reconciliation and clear error codes are not advanced features. They are the minimum evidence that the integration has been designed for production.

Contracts need an owner

Every contract should have a named owner on each side. The owner is accountable for the meaning of the data and for communicating change. When ownership is absent, versioning becomes a negotiation after the break.

We prefer to record contracts in a lightweight catalogue that is part of the delivery process. The catalogue does not need to be a large platform; it needs to be the place people look before changing an interface.

Versioning is a product decision

A version is a promise about compatibility, not just a number. Some changes can be additive; others require a new version and a migration period. The decision should be based on who depends on the contract and what it will cost them to change.

What we recommend

  • Document semantics, ownership, freshness, failure behaviour and change process for every integration.
  • Use idempotency and replay as default design patterns, not exceptions.
  • Maintain a contract catalogue that is updated as part of delivery.
  • Agree a versioning and deprecation policy before the first external consumer.
  • Monitor the contract, not just the infrastructure: volume, latency, rejects and reconciliation.

Where we disagree

We do not believe an enterprise service bus or API gateway solves integration by itself. Those tools provide useful capabilities, but they do not define meaning or assign ownership. We also do not believe every integration should be event-driven; synchronous calls are often the simpler and more honest choice.

A practical test

Take the most important integration in your estate and ask three questions: who owns the meaning of each field, what happens when a message is rejected, and how a consumer will be told about a breaking change. If those answers are not written down, the integration is running on assumptions. The first step is a contract, not a new platform.

Our position is not that every organisation should follow the same path. It is that the trade-offs should be explicit before the commitment is made.