Designing and Evolving APIs

Blogs· 5min June 20, 2022

Arnaud Lauret aka. "The API handyman" is an OpenAPI Lead at Postman. He joins us to share his expertise on API design and maintenance, including tips for evolving APIs and how the OpenAPI specification can make the lives of API designers easier.

Arnaud Lauret is currently working on the Postman Open Technology team. The team educates engineers and organisations to take advantage of APIs. Arnaud shares his knowledge on his blog apihandyman.io and has also written the book "The Design of Web APIs".

What is an API?

Historically, APIs have been thought as remote interfaces that allow software to communicate over a local network or the Internet. Now, they are interfaces that allow to provide a service that others don't want to build from scratch. If you build something really well, you can turn it into an API for others to leverage. For example, Stripe or Twilio allow to build payments or communication simply.

In order to be easy to use, APIs should be consistent, so that users don't have to change their integration often. The consistency of an API allows users to guess how it will work, without having to read the documentation. Arnaud is in favour of consistency and should always be the first choice of API designers.

However, sometimes design patterns simply don't fit the problem. It can be a tricky tradeoff to choose between providing a suboptimal solution that fits your design and a better solution that surprises users. Arnaud prefers to introduce a new pattern to fit the usecase, as opposed to forcing a pattern that doesn't really fit.

Evolving APIs

APIs can become difficult to change if some poor design decisions are made in the very beginning. You need to prepare your APIs to accept change gracefully. Here are some things you can do:

Choose extensible data types.

  • Prefer strings over booleans to represent statuses. This will allow you to change your workflows and add new statuses as required.
  • Encapsulate data in objects, wrapping lists, atomics or responses. This will allow you to add metadata alongside anything you return without the need to make breaking changes.

Create workflows with independent usable steps.

  • Workflows typically map the users workflows. If a changes comes from the users, then the API will have to change the mapped process as well.
  • Building workflows in reusable steps will allow others to use the workflow as well.

Keep things as simple as possible.

If you do need to make a breaking change, Arnaud recommends a middle step. For example, if you have a status as a boolean, then you can add a new string field and deprecate the old status. If you do this in the beginning, then you will begin to get a better idea of the domain that your API is representing. Perhaps your API won't be as beautiful as you wish, but it will still deliver functionality to your users.

Then, when you introduce new features/functionality in your API, you can clean up your interfaces and let your consumers know how to adjust to match the new version.

However, you will have to provide multiple versions of your API as users migrate to the new functionality. To do that, you have two options:

  • Duplicate your infrastructure with multiple implementations running side by side. This is not recommended as multiple backend services will have to handle the versions.
  • Have a single implementation that will be able to expose the multiple contracts of your API versions. Older requests can be mapped to the new version internally and other services only need to handle one request. The Stripe API uses this transformation strategy in production.

GraphQL

Arnaud has mixed feelings regarding GraphQL, which was developed by Facebook to make API design easier. However, it does not prevent introducing breaking changes, even though it allows easier testing.

It solves some problems regarding performance, but you still have to design your APIs and models. You gain visibility on how your API is used, but you lose the ability to read the usage of it easily.

The OpenAPI specification

The OpenAPI specification is a machine readable, but human friendly format to describe REST web APIs taking advantage of the HTTP protocol.

The specification, formerly known as the Swagger specification, was originally used to document APIs. Then, it was used in a design first approach to describe your API once you know what you want it to do. You can then use the specification to generate documentation, code, clients, mocks and tests, as well as configure API gateways. It can also validate that your API is satisfying your organisation's requirements.

There are many uses of the specification and we are just scratching the top of it! Make sure you take advantage of the OpenAPI ecosystem if you are designing your APIs.

Written by

github-icongithub-icongithub-icon
Adelina Simion Technology Evangelist

Adelina is a polyglot engineer and developer relations professional, with a decade of technical experience at multiple startups in London. She started her career as a Java backend engineer, converted later to Go, and then transitioned to a full-time developer relations role. She has published multiple online courses about Go on the LinkedIn Learning platform, helping thousands of developers up-skill with Go. She has a passion for public speaking, having presented on cloud architectures at major European conferences. Adelina holds an MSc. Mathematical Modelling and Computing degree.