Architecture
API Versioning and Deprecation Without Breaking Your Customers
Updated April 16, 2019By the CalliArc team
Key takeaway
Add fields freely; never remove or repurpose them within a version. When a breaking change is unavoidable, run the old and new versions in parallel, announce a dated deprecation with usage data telling you exactly who still calls it, and contact those customers directly.
Once someone else's production system calls your API, you've made a promise. Versioning is how you keep that promise while still being able to change things.
Know what's breaking
- Breaking: removing or renaming a field, changing a type, adding a required parameter, tightening validation, changing an error code, or altering the meaning of an existing value.
- Not breaking: adding an optional parameter, adding a new field to a response, adding a new endpoint or a new enum value — provided you documented that clients must tolerate unknown values.
- The grey area is behaviour: changing pagination defaults or sort order breaks consumers who relied on it, even though the schema is unchanged.
Versioning strategies
- URL path versioning (/v1/) — unambiguous, easy to route and cache, obvious in logs. The pragmatic default.
- Header or media-type versioning — cleaner in theory, harder to test and debug, and frequently mishandled by intermediaries.
- Date-based versions pinned per API key — powerful for large platforms, and significant work to maintain.
- Whichever you pick, version the whole API rather than individual endpoints; per-endpoint versions become unmanageable quickly.
Running a fair deprecation
- Announce with a specific end date, not "soon", and publish a migration guide with before-and-after examples.
- Give a reasonable window — six to twelve months for a widely used API, and longer for enterprise integrations with their own release cycles.
- Return a deprecation header on every call to the old version, so it shows up in the integrator's logs.
- Use your own usage data to identify affected customers and email them individually; a changelog entry alone will not reach the person who wrote the integration three years ago.
- Consider brownouts — short, scheduled outages of the old version near the end — so nobody is surprised on cutover day.
Reduce how often you need this
- Design responses to be extensible from the start, and document that clients must ignore unknown fields.
- Avoid leaking internal models directly; an API shape tied to your database schema breaks every time you refactor.
- Publish a machine-readable specification and run contract tests so an accidental breaking change fails your build rather than a customer's.
- Keep a changelog. It's the cheapest possible tool for maintaining integrator trust.