At QCon San Francisco 2022, Brandon Byars, North America head of technology at ThoughtWorks, presented his journey of API Evolution without Versioning, in particular, evolution patterns from examples from his 9-year-long project mountebank. The talk is part of the editorial track, Modern APIs: Building and Evolving.
API Versioning has been an important part of developing public REST APIs. But breaking changes and asking your users to upgrade is not free. Brandon mentioned that as API architects, we should evaluate API changes and options "from a consumer’s perspective"; in three categories: obviousness, elegance, and stability.
Brandon examined and evaluated six evolution patterns used in the evolution of mountebank: change by addition, multi-typing, upcasting, nested upcasting, downcasting, and hidden interfaces. Brandon notes that forward compatibility can really make an impact, pay future dividends, and give you a fighting chance to avoid future breaking changes. Brandon wrapped the added parameter in a nested object in his example to allow future extensibility.
Upcasting was Brandon’s favorite pattern. Upcasting enables and extends new functionalities by accepting an array while keeping backward compatibility with the existing data type. On the implementation level, the complexity module transforms the previously supported data type to the new supported data type to minimize the complexity of the core logic. Once the new interface was made available, the previously accepted data type was no longer publicized on the API documentation.
Another reason that Brandon really likes upcasting is that you can nest multiple upcasts inside each other. On the implementation level, you can add more upcasts in chronological order to achieve multiple upcasts using the same upcast hook.
Brandon emphasizes that APIs are promises and not guarantees. Hyrum’s law applies to APIs with enough users. API architects should empathize with the API users. Making tradeoffs and decisions as APIs evolve is not only engineering but also a product management concern and should be evaluated within a product framework. He further explains the model he used when evaluating these tradeoffs:
-
Viability - are we solving a problem our users have?
-
Usability - are we making it easy to use our product?
-
Feasibility - can we do this in an architecturally sound way?
After the talk, Brandon told InfoQ that he also recommends applying the same principles to internal APIs. For teams that operate closely together, there are more patterns, such as expand-and-contract, to give people time to upgrade before deprecating legacy behaviors to achieve evolution without versioning as well.
Lastly, note that the talk on modern APIs, building modern backends, and most other conference presentations will be recorded and made available on InfoQ over the coming months. The next QCon conference is the QCon plus online.