At xMatters, we follow the SemVer specification – we update the API major version whenever we introduce breaking changes. Internally, we update minor and patch versions whenever we add functionality and backward-compatible updates. When we release a new major version of the xMatters REST API, clients can choose to either continue using an existing major version or migrate to the new one.
One of the major challenges surrounding exposing services is handling updates to the API contract. Clients may not want to update their applications when the API changes, so a versioning strategy becomes crucial. A versioning strategy allows clients to continue using the existing REST API and migrate their applications to the newer API when they are ready.
There are four common ways to version a REST API.
1. Versioning through URI Path
One way to version a REST API is to include the version number in the URI path.
xMatters uses this strategy, and so do DevOps teams at Facebook, Twitter, Airbnb, and many more.
The internal version of the API uses the 1.2.3 format, so it looks as follows:
- Major version: The version used in the URI and denotes breaking changes to the API. Internally, a new major version implies creating a new API and the version number is used to route to the correct host.
- Minor and Patch versions: These are transparent to the client and used internally for backward-compatible updates. They are usually communicated in change logs to inform clients about a new functionality or a bug fix.
This solution often uses URI routing to point to a specific version of the API. Because cache keys (in this situation URIs) are changed by version, clients can easily cache resources. When a new version of the REST API is released, it is perceived as a new entry in the cache.
- Pros: Clients can cache resources easily
- Cons: This solution has a pretty big footprint in the code base as introducing breaking changes implies branching the entire API
2. Versioning through query parameters
Another option for versioning a REST API is to include the version number as a query parameter.
This is a straightforward way of versioning an API from an implementation point of view.
- Pros: It’s a straightforward way to version an API, and it’s easy to default to the latest version
- Cons: Query parameters are more difficult to use for routing requests to the proper API version
3. Versioning through custom headers
curl -H “Accepts-version: 1.0”
REST APIs can also be versioned by providing custom headers with the version number included as an attribute.The main difference between this approach and the two previous ones is that it doesn’t clutter the URI with versioning information.
- Pros: It doesn’t clutter the URI with versioning information
- Cons: It requires custom headers
4. Versioning through content negotiation
curl -H “Accept: application/vnd.xm.device+json; version=1” http://www.example.com/api/products
The last strategy we are addressing is versioning through content negotiation.
This approach allows us to version a single resource representation instead of versioning the entire API which gives us a more granular control over versioning. It also creates a smaller footprint in the code base as we don’t have to fork the entire application when creating a new version. Another advantage of this approach is that it doesn’t require implementing URI routing rules introduced by versioning through the URI path.
One of the drawbacks of this approach is that it is less accessible than URI-versioned APIs: Requiring HTTP headers with media types makes it more difficult to test and explore the API using a browser.
- Pros: Allows us to version a single resource representation instead of versioning the entire API, which gives us a more granular control over versioning. Creates a smaller footprint. Doesn’t require implementing URI routing rules.
- Cons: Requiring HTTP headers with media types makes it more difficult to test and explore the API using a browser
Versioning is a crucial part of API design. It gives developers the ability to improve their API without breaking the client’s applications when new updates are rolled out.
Content negotiation is a more granular approach because it versions resource representations instead of versioning the entire API, but it also comes with a high implementation cost for both clients and developers. More often than not, content negotiation needs to be implemented from scratch as there are few libraries that offer that out of the box. The other approaches are easier to implement and use but limit the developer’s ability to refactor due to the high cost of introducing breaking changes to the API contract.
Do you have a different strategy for API versioning? Do you have experience with these strategies? Let us know on our socials! To try xMatters for yourself, race to xMatters Free, and you can use it free forever.