beginner 2 min answer

A platform team argues that their internal API needs no versioning because every caller is inside the company and can be found with a code search. What is wrong with that reasoning?

internal apiversioningcouplingdeploymentcompatibility
Show the full answer Hide the answer

The reasoning being tested

The argument confuses knowing who the callers are with being able to change them at the same moment. Even with a complete list of consumers, a breaking change requires every caller to be updated and deployed simultaneously, and in an organisation of any size that does not happen. Between the first deploy and the last, two versions of the caller exist against one version of the API.

What actually goes wrong

  • Deploys are not atomic across services. During a rolling deploy, old and new instances of the same service run side by side for minutes. A breaking change therefore has to survive at least that window even if only one consumer exists.
  • Rollback becomes impossible. If the API changed and callers were updated, rolling the API back breaks the updated callers. Compatibility is what makes a change reversible, and reversibility is worth more than elegance in the hour after a bad deploy.
  • Code search misses real callers. Configuration, scripts, a Terraform provider, a partner integration, a retry from a queued job written yesterday. Search finds source, not traffic.
  • Queued work carries old requests. A message produced before the change is consumed after it, so the wire format must span the queue's retention, not the deploy window.

What internal APIs can legitimately skip

This is not the argument that internal APIs should be treated like public ones. Internal consumers give you two real advantages: you can see usage directly, and you can set a deprecation deadline that is measured in weeks rather than years. So skip the long support windows, the semantic-version ceremony and the parallel documentation sets — and keep the compatibility discipline, because that one is about deployment mechanics, not about who the consumer is.

The workable position for most platform teams: additive changes any time, breaking changes via a new path or field with the old one maintained until usage telemetry shows zero, and a deprecation window measured against observed traffic rather than against a calendar.

Common weak answers

  • "We'll coordinate a flag day." Flag days work at three consumers and fail at thirty. They also require every consumer to be deployable that day, which is the assumption that breaks.
  • "We'll just fix the callers when they break." This moves the cost from the team making the change to the teams receiving it, which is exactly the dynamic that makes internal platforms unpopular, and it converts a planned change into several unplanned incidents.

The rule to take away: choose compatibility windows from deployment mechanics, not from consumer count. Even with 1 consumer, the window must cover the rolling deploy, which is minutes, plus the retention of any queue carrying requests, which since the rise of durable job queues in the 2010s is routinely 7 days. That is the floor, and it does not shrink because everyone works for the same company.