If we are developing a library and want to introduce a breaking change, we can simply bump the major version and publish it. Developers can freely choose if, and when, they want to migrate. However, the process is not so trivial for APIs because for the following reasons:
- For every version of the API, the API provider must serve and maintain a different instance of the service. This can be a huge overhead.
- Different versions of the API would still use the same set of data, so you must design a data structure that is compatible with all versions. Sometimes, this may require you to have redundant fields in your data.
- If the changes are too drastic, developers may keep using the older version, possibly prolonging the period for which you must support the older API.
Breaking changes are also bad for developer experience because for the following reasons:
- Developers are often given a limited period of time to update their code to conform to the newer version, before the older version is dropped.
- Third-party libraries that depend on your API would also have to update their code. But if maintainers lack the time or willingness to migrate, it could lead to an accumulation of outdated libraries.
For these reasons, breaking changes should be avoided as much as possible. When you design your API, take care not to just think about the current requirements, but also any possible future needs.
This does not contradict the you aren't gonna need it (YAGNI) principle. You're not going to implement a feature you may not need. You are just going to think ahead, so you can plan ahead.