How to Manage Breaking Changes Throughout an API’s Lifecycle Posted in Design Kristopher Sandoval April 26, 2023 Breaking changes can cause headaches for users and developers alike. Having a software dependency work one day and suddenly break the next can be an infuriating experience. Thankfully, with proper planning and management, breaking changes can be managed effectively throughout the API lifecycle. Defining a Breaking Change The reality of APIs is that change occurs throughout the entire product lifecycle. Often, the form and function of an API can be radically different at the end of its life than in its initial development, with developers reacting to market changes, business adjustments, new feature requests, and more. Along the path between the first viable product to the sunsetting of the API, these changes typically happen over multiple revisions, with minor changes adding up over time. A breaking change is when one such change causes a client application to break somehow. While some changes make a minimal impact, breaking changes are those fundamental changes that cause the system to cease functioning. This could be a change in a field name, the removal of an unused resource type, a new feature that deprecates older features, and so forth. Why Breaking Changes Can Be Disastrous Breaking changes are challenging to manage because users often act in ways that are unknown to the API provider. (This is sometimes referred to as Hyrum’s Law). These unknown actions might include using deprecated systems for their own core functions or utilizing older codebases for compatibility purposes. Developer consumers may simply not pay attention to change announcements, to the point that systems become outdated. Another major issue with breaking changes is that APIs often act in concert with one another. Because of this, you can never be quite sure what API or system utilizes your own for critical downstream functionality. In some cases, such as organization-specific API implementations, this issue may be less of a problem. But for public or partner-facing APIs, a breaking change can have a cascading effect across a larger userbase. Of course, it is not the sole responsibility of the developer to support all of these unknown situations, but having a firm understanding of breaking changes — and how best to handle them — is a skill developers should hone. 7 Ways to Manage Breaking Changes 1. Avoid Breaking Changes This seems like a non-sequitur, but the easiest way to manage breaking changes is simply to avoid them. Not all breaking changes are necessary, and planning ahead of time and ensuring the API’s portability and extensibility can help prevent these changes. That being said, not every breaking change can be avoided. When you must implement them, there are quite a few things you can do to manage their impact and ensure a continued positive experience. 2. Plan for Retirement Now APIs and the components which comprise them have a shelf life. When APIs are created, each piece should be assumed to be time-limited. Some day they will be removed, replaced, or deprecated, either in whole or in part. This becomes a breaking change when the developer, and the user base, do not adequately plan for this eventuality. This planning can take various forms. For example, if you consider that a function may someday be deprecated, failover functions or systems should be included to either route the request to other endpoints or provide a notification system. Having a plan for how you deprecate parts or the entire API will make sure that breaking changes that occur along the way are planned and accommodated correctly. 3. Group Breaking Changes into Singular Updates Breaking changes can’t always be avoided, and even the best planning will ultimately run into a situation where developers must choose between functionality or avoiding breakage. When a breaking change must be made, the process of implementing that change can also dramatically change the difficulties introduced. Breaking changes can occur over multiple systems, but ultimately, the end user will only experience the API as a whole. Breaking changes in a proper versioning system will result in a user migrating to a new version. Accordingly, implementing breaking changes individually can result in a collection of different versions, and the expense and difficulty of generating buy-in from users for each version can be a major issue. To solve this, developers can bundle their breaking changes into a single major update. This often takes the form of a major numbered revision. For example, a collection of 10-15 breaking changes and minor updates might be bundled in an “API v2.0” release, denoting a significant change from version 1.0 that requires additional buy-in. Bundled releases like this will not reduce the cost of generating buy-in and understanding, but it will reduce the number of times this is necessary, allowing your users to do a single, simple upgrade, thereby improving their experience. 4. Establish Effective Communication Channels Communication is incredibly important when it comes to breaking changes. Breaking changes are not necessarily a problem in and of themselves as much as they are a precipitator of other issues, many of which can be solved through proper communication behind the intent of the change, the potential impact on users, and the plan for implementing such changes. It should be noted that having a single communication channel is not good enough. An effective communication strategy for breaking changes should have several systems and channels working in tandem to be truly effective. Simply sending out a changelog and hoping for the best doesn’t really solve the problem. Alternately, sending an email to registered users, updating the knowledge base, utilizing social media to reach out to users reporting issues, and even offering live support for premium clients can go a long way towards mitigating the impact of a majorly breaking change. 5. Leverage API Responses One effective channel of communication that is often overlooked is the API response itself. Developers can use API responses themselves to communicate vital information about both the underlying resource structure and the breaking changes that might impact them. For instance, when a breaking change is implemented that results in the sunsetting of a particular function or underlying resource, developers can make use of the now defunct endpoint to alert the user that the function is now deprecated, linking to the resource documentation with additional information about upgrading to a new version. The endpoint can also be used as a routing system. When functions are combined and ported to a new endpoint, old endpoints can still be used to route the request and transform it for the new endpoint. While this doesn’t necessarily solve the problem of using deprecated endpoints, additional warnings and data can be served at the same time as the response itself, alerting users that they should move to the proper endpoint due to the change. 6. Future-Proof Documentation Documentation is ultimately the most effective methodology for sharing the rationale and design of an API. As such, documentation can be used to inform the user as to the planned development of the API, including breaking changes, sunsetting, deprecation, and so forth. Documentation should be future-proofed. Designing documentation to be automatically created, tested, and maintained is a big first step toward this process, as out-of-date documentation is as good as no documentation at all. Also, consider documenting breaking changes in a dedicated section in the developer portal, linked to by changelogs, sections within each documentation description for the broken systems, and referenced internally and externally as a source of truth. To go a step further, this documentation should be used as a reference point in all communication about the breaking changes. Are you using your API response to alert the user to a breaking change? That alert should also connect to the documentation. Are you talking to a user on social media about a deprecated function? Point to the documentation. Ultimately, the documentation should be a source of truth. 7. Set Clear and Realistic Timelines Finally, developers should set clear and realistic timelines for breaking changes. The simple fact is that no user will be able to make a massive change in a single day to their APIs. Choosing to break an API only makes sense if the functionality it replaces it with is adequate to deliver the same end result. This includes providing the time necessary to build, iterate, and deploy at scale. Set clear and realistic timelines for adoption. This may mean creating a sunsetting or deprecation plan, alerting users as to the breaking changes with ample time before release, or even releasing a roadmap for API development well in advance of any development. Understanding that users are humans and that they will need clear and realistic timelines will go a long way towards ensuring that your value offering is maintained and that the usefulness of your API is not fundamentally broken, no matter how breaking the change. Conclusion What do you think of this advice? Did we miss any major steps one can take to avoid breaking changes through an API’s lifecycle? Let us know in the comments below!