10 Steps to Safely Change an API

I would not describe myself as an API developer per se but at this point most developers probably qualify as ‘API developers’. If you are not writing the front end the user sees then you are writing code and interfaces that other developers rely on. Be it a library, framework or a REST API. And a topic that does not get enough attention is how to safely change an API. There are any number of reasons that your API might change.

Maybe your clients changed, maybe your service changed, maybe the original API was written by an intern. Eventually you’ll need to change your API.

Imagine you are making a straightforward, but breaking API change. For example you return Person(s) with a ssn field of type long. This worked great in the U.S. market where most citizens have Social Security Numbers but now your product is global and you need something more generic such as a state_id field

The simple way of doing this is:

  1. Start writing the new state_id field.
  2. Switch all the the clients to read from the state_id field.
  3. Remove the ssn field.

However just doing these steps is not always sufficient and can break your clients.

Safely changing an API is complicated, it benefits from having a checklist.

(I’m disregarding the topic of versioning since it is not available in all cases.)

  1. Talk to all your clients about adding the field. They might be aware of non obvious dependencies in their code on the ssn. You could reasonably guess where someone was born from their Social Security Number up until 2011. You want to make sure they are not doing anything ‘clever’.

    I once had a client who was reflectively reading all the fields and was checking that only the fields they were expecting were being populated and threw an error if an extra field existed. This will also ensure that your clients know that they will need to start reading from the new field (Step 5).

  2. Talk to all the clients of your clients about adding the field. Your direct clients might just be passing your representation of the data through to their clients. This means that instead of breaking your direct clients, who know you and you hopefully have a good working relationship with, you will break another team you never met.

    Now they’re annoyed with you, and you’re asking them to change their code.

  3. Add the new field but set the value to null (assuming your language supports it). Doing this as a separate step means that you can start working on Step 6 in parallel to steps 4 and 5.

  4. A/B populate the new field. In a lot of cases doing steps 3 and 4 together is perfectly safe. However if the new field is large or the client has resource constraints you might increase the load on the client too much. This is surprisingly easy to do if the client is a mobile phone or embedded device. It can also happen if you have a popular mobile app and have each phone start sending a few hundred kilobytes extra per second the load on your server goes up pretty fast. It is much easier to provision for this if you gradually have the field be populated.

  5. As soon as you are confident Step 4 worked mark the field as deprecated. Either through using a @Deprecated annotation or comment explaining what field to read from to get the new data from. This saves you from having new clients accidentally read from the old field that you are trying to get rid of.

  6. Add code to clients to read from either field, with a preference for the new field. e.g.

     if(response.national_id != null){
         return response.national_id.ssn;
     }
     else if (response.ssn != null) {
         return response.ssn;
     }
    

    Switching the client code to read from either field has two advantages. Firstly you can have your clients update before you are ready to start writing the actual values. Which means you can start on Step 6 in parallel to steps 4 and 5. It is also safer for the client in the rare case that you have to reverse Step 4.

  7. Tell your clients you will be removing the field. You want to do this at least three times. A month before, a week before, and the day of. The month before email is to make sure people did not forget about anything, or ignore all your previous communications. The week before is a C.Y.A. in case anything breaks you can say “Hey I gave you plenty of notice”. The day of email is so if anything does break the change will be fresh in their minds.

  8. Switch off writing the old field. As in Step 4 do this with an A/B flag. That way if someone forgot to update their code and is still reading from the old field you can easily turn back on writing it.

  9. Remove reading of the old field from all of the clients. You want this change to be in production before Step 10 so as not to cause any issues with the old field being missing.

  10. Remove the old field.

Those are (I think) the 10 steps to safely change an API.