practice

Deployment Compatibility Check

also called Can-I-Deploy, Deployment Gate on Contracts

A pre-deployment query asking whether this version is compatible with everything currently deployed - which turns contract tests from a test into a release gate.

contract-testingdeploymentversioningbrokerrelease-safety

Contract verification in a build answers "does this change break any registered consumer contract?" That is useful and incomplete, because it does not account for which versions are actually deployed where.

A deployment compatibility check answers the operational question: given what is currently running in this environment, is it safe to deploy this version?

The broker records which consumer and provider versions are deployed in each environment, and the check verifies compatibility against that set rather than against every contract ever registered.

Why it matters at scale

Verifying against all historical contracts is both too slow and too strict. It blocks a provider change because a consumer version nobody runs any more depended on a field — and it makes every provider build slower as consumer count grows.

Verifying against nothing is too permissive: a change that passes its own tests can still break a consumer that is currently deployed.

The deployed set is the correct scope, and it is only knowable if deployments are recorded.

Implementation patterns

  • Record every deployment to the broker — which version, which environment, when. This is the prerequisite and the step teams skip.
  • Include pending deployments, so a provider does not deploy something incompatible with a consumer that is about to release.
  • Fail the deployment, not just the build, so the check is a gate rather than information.
  • Report which consumer is incompatible and how, so the failure is actionable rather than a support request to another team.
  • Support a deliberate override with a record, for the case where the incompatible consumer is being retired anyway.
  • Treat the broker as production infrastructure, with SLOs, because it is now on the critical path of every deployment.

Industry example

Organisations with hundreds of independently-deploying services find that contract verification alone does not prevent incidents, because the question at deployment time is different from the question at build time.

The check closes that gap, and it produces a second benefit that is frequently the one teams value most: the broker's record of deployed versions and their contracts is the authoritative answer to "who uses this field" — which is exactly what makes deprecation possible.

At that scale, "which fields does anyone actually use" is otherwise unanswerable, and its absence is the dominant reason interfaces ossify.

Failure scenarios

  • Deployments not recorded, so the check has no data and either passes everything or blocks everything.
  • Environments not distinguished, so a staging deployment blocks a production one.
  • The broker unavailable, which now blocks all deployments — requiring an explicit fail-open or fail-closed decision made deliberately.
  • Overrides used routinely, at which point the gate provides nothing.
  • Contracts encoding behaviour rather than interface, so the check fails on legitimate changes and is bypassed.

Trade-offs

The check adds a dependency to the deployment path and requires deployment recording discipline. It also introduces a decision about behaviour when the broker is unreachable — fail-closed is safer and blocks deployments during a broker incident; fail-open keeps deploying and forfeits the guarantee.

For a small number of services with coordinated releases it is unnecessary. It becomes valuable exactly when independent deployment makes the compatibility question unanswerable by inspection.

Interview question

"Your provider's build passes all contract tests and deploying it breaks a consumer. Explain how, and tell me what check would have caught it."