Best practicing for implementing API versioning

At work we’re building an iOS and Android app that both talk to same API. We are now in a position where we need to make some breaking changes to the API. To not break versions of the apps that have already been shipped we need to version the API.

I’m having a hard tim figuring out how to do that, coding wise. These are the solutions I’ve been able to think of so far, none of which seem very compelling:

  1. Duplicate all classes that need to change into a new namespace called V2 and call those from the V2 controllers. This leads to twice the amount of code and twice the amount of tests.
  2. Make version 2 classes that inherit from version 1 classes. This leads to potentially very deep inheritance hierarchies down the road.
  3. Use decorators instead of inheritance. Seems to have the same problem as 2 and its also not immediately obvious when writing new code which decorators would have to be applied in order to get the behaviour for a specific version.
  4. Run two completely separate versions of the API. Would double the hosting price and they would need to talk to the same database anyway so that’d probably get us into trouble at some point.

I’m not sure which of these solutions would be the best. Anyone who has experience they wanna share? Would be very appreciated :smile:

So I worked on a project with a small team. We all agreed that
supporting multiple API versions was not really feasible given our
size, and even if we where a larger team we agreed we would still not
want to ever have to support multiple API versions. But we recognized
that braking API changes where inevitable, and we need a strategy to
address it when it happened.

What we did was agree we would only want to support one API version at
a time, but if braking changes where introduced we would be willing to
support two API versions with the goal being to sunset and remove the
older version as quickly as possible. To support this we added code in
the iOS and Android apps that would allow the server to explicitly
inform the client that the version of the API the requested will soon
be deprecated, or is now depricated and was no longer available. This
allowed the app to direct the user to update the app to a newer
version.

Under the hood in the Rails app we scoped requests to a module based
off of a constraint match. We used the
scope method
in our routes file and set the module to the API version’s module
for the route scope, and set the constraints option to a matcher
object that would read the Accept header and extract the API
version. So when a new API version need to get cut, we simply need to
copy wholesale the current API’s code and rename it. After that we
could make our changes, push the code, monitor the usage to the old
API version. To inform users making requests to the old API version
they need to start upgrading; the server would either rewrite status
codes or a set custom X Header indicating the API they are using will
soon become deprecated and direct them to upgrade. Once traffic
dropped we could delete the old API version’s code and be back to our
desired one API at a time world. We need to also create a catch all
scope for the deprecated API versions that would respond with a
specific status code and error so that API consumers would know the
API was deprecated - this is key to helping make sure people with the
iOS and Android app know they need to install a new version of the
app.