Non-breaking API changes

Learn about helping others to handle your version of software, compatible API changes, HTTP for connection handshaking, breaking network agreements and and safe changes.

Minimizing work transference to other teams

We now know how to design applications so that they can be deployed easily and repeatedly. That means we also have the ability to change the way our software talks with the rest of the world easily and repeatedly. However, as we make changes to add features, we need to be careful not to break consuming applications. Whenever we do that, we force other teams to do more work in order to get it running again. Something is definitely wrong if our team creates work for several other teams! It’s better for everyone if we do some extra work on our end to maintain compatibility rather than pushing migration costs out onto other teams. This chapter looks at how your software can be a good citizen.

Help others handle your versions

It won’t come as a surprise to learn that different consumers of our service have different goals and needs. Each consuming application has its own development team that operates on its own schedule. If we want others to respect our autonomy, then we must respect theirs. That means we can’t force consumers to match our release schedule. They shouldn’t have to make a new release at the same time as ours just so we can change our API. That is especially true if we provide SaaS services across the internet, but it also holds within a single organization or across a partner channel. Trying to coordinate consumer and provider deployments doesn’t scale. Follow the ripple effect from our deployment and we might find that the whole company has to upgrade at once. That means most new versions of a service should be compatible.

Non-breaking API changes

In the TCP specification, Jon Postel gave us a good principle for building robust systems from disparate providers. Postel’s robustness principle says, “Be conservative in what you do, be liberal in what you accept from others.” 1^{1} It has mostly worked out for the internet as a whole (subject to a lot of caveats from chapter Security) so let’s see if we can apply this principle to protocol versions in our applications.

Compatible API changes

In order to make compatible API changes, we need to consider what makes for an incompatible change. What we call an “API” is really a layered stack of agreements between pieces of software. Some of the agreements are so fundamental now that we barely talk about them. For example, when was the last time you saw a network running NetBIOS instead of TCP/IP? We can assume a certain amount of commonality: IP, TCP, UDP, and DNS. Multicast may be allowed within some boundaries in your network, but this should only be used within a closed set of hosts. Never expect it to be routed between different networks. Above that, we are firmly in layer 7, the application layer. The consumer and provider must share a number of additional agreements in order to communicate. We can think of these as agreements in the following situations:

  • Connection handshaking and duration
  • Request framing
  • Content encoding
  • Message syntax
  • Message semantics
  • Authorization and authentication

HTTP for connection handshaking

If we pick the HTTP family (HTTP, HTTPS, or HTTP/2) for connection handshaking and duration, then we get some of the other agreements baked in. For example, HTTP’s “Content-Type” and “Content-Length” headers help with request framing.

Get hands-on with 1400+ tech skills courses.