Prototype-First API Design

Prototype-First API Design

Posted in

Discussions of API design approaches generally fall into two camps: code-first and design-first. Each has different tradeoffs, with design-first typically perceived as ideal but not always practical.

In this article, I’ll present a third option, prototype-first, and argue that this combines several benefits from the other two approaches.

Design-First

Design as a distinct activity isn’t a popular concept in software development today. Most of the time, the thinking goes that software is easy to change and pressure is always high to ship new things. As such, design is often viewed as something that should emerge incrementally rather than being “done.”

However, this isn’t always the case with APIs. If you’re in the business of building APIs for consumption outside of your team, group, or company, the impact of poor design decisions can be severe and long-lived. Once an API has customers, you’re bound by the need to maintain backward compatibility and consistency.

With this in mind, some up-front design is often a good idea versus just shipping the first thing that seems to work and assuming you’ll find a way to fix it later.

Why Design-First Falters

Even if you accept the premise above, the pressure to deliver ASAP doesn’t disappear. When you’ve got teams of mobile, web, or data developers sitting on their hands waiting for a new API capability to build against, it’s very tempting to just release something as soon as possible and worry about design afterward. This is a common reason API design-first approaches are either not adopted or abandoned by organizations that would benefit from them.

Then, there’s a second issue: designs (of any kind) only improve when meaningful feedback is possible. API designs can be inspected, and some useful feedback results from this, but they can’t be used. Effective feedback in software often arrives as a series of “doh!” moments when actually trying something, so the earlier we instigate this process by getting an API into the hands of its consumers, the better.

This is why I believe that API design shouldn’t start on the whiteboard, but instead from a prototype.

So How Does Prototyping Help?

An API prototype, unlike a design document or specification, can be used immediately by its consumers. The client code is written, and app features are built early on.

With the right tooling, a prototype should be far quicker and easier to create, publish, and modify than the real thing. This means that feedback can be gained early, and the learning can be incorporated into the design immediately for testing.

Even when the API design is essentially correct the first time (which is usually what happens, right?), having a prototype enables consuming teams to make progress on their features in parallel with the API-producing team.

Approaches to Prototyping

Some teams do a form of API prototyping directly in their production code by creating minimal, non-functioning, or stubbed scaffolding code for route handlers and data models, then shipping the code to a test environment. They might also generate OpenAPI from the code in order to document this design and facilitate a review process. If you’re doing this, you might not necessarily call it prototyping, but this is essentially what it is.

However, this approach is less than ideal for several reasons.

Firstly, each change to the API design involves a code->push->build->deploy cycle before the change is visible to other stakeholders. In all but the most well-tuned CD pipelines, this adds a lot of friction when making a series of design iterations.

Secondly, providing stubbed responses in code is limiting. The API producers are the only group that can add to the range of responses available, and this is time-consuming, both in terms of making the changes and deploying them. Non-happy paths, error, and fault responses can be hard to create on-demand, and getting decent diagnostic info may also require further effort.

Mocks as Prototypes

API mocking is often a better solution here. Mocks are inherently far cheaper to build, publish, run, and modify than services running production code (even on modern serverless tech stacks).

A mock API can be produced live during design collaboration sessions between producing and consuming teams. Then, they can be made available immediately for consuming teams to start building against. This allows for rapid feedback on the API design specs before costly implementation decisions have been committed to by the producer.

Some tools support OpenAPI generation from a mock, so in these cases, you can save considerable effort in creating a full design spec. You can focus on adding descriptive elements and schema details rather than creating the whole spec from scratch.

Mocks also retain their value after the real API feature has been shipped as they enable fast, deterministic continuous testing — their primary use case in most teams today.

Brownfield Prototyping

One objection sometimes heard about API mocking versus prototyping directly in the production code is that, more often than not, we’re adding features to an existing API rather than creating a new one. We have an existing set of API features we’re happy testing against and don’t want to have to build mocks for all of these just so that we can mock the new one.

However, many mocking tools support some kind of proxy-based “partial mocking” pattern whereby calls to API endpoints that are already implemented get passed to a test environment, while endpoints still under development are mocked. To the caller these are indistinguishable — it all looks like a single API.

Long-Term Value

API mocks that are actively maintained continue to provide value to API consumers beyond the prototyping phase. Even when a production implementation of an API is available there are many benefits to testing consuming code against mocks. Benefits include faster and more reliable CI builds, easy fault and chaos testing, and reduced data setup effort, to name a few.

Quite often, consuming teams create mocks of APIs they don’t own to get these benefits. In larger organizations, this creates duplication of effort as multiple consumers mock the same API. In this case, a well-maintained mock provided by the team that owns the API is a big aid to productivity.

Additionally, for organizations that publish APIs to their customers, mocks can significantly enhance the developer experience for consumers by providing low-friction access to an environment they can start to integrate with and showcasing specific interactions, especially the secondary and sad paths that can be difficult to reproduce reliably in production-like sandboxes.

In Summary

Producing well-designed, easy-to-use APIs is becoming increasingly critical to business success. API prototyping with mocks offers a way to balance time-to-market, productivity, and quality in API-centric companies.