Search⌘ K
AI Features

Important Concepts in Product Architecture - I

Explore essential concepts in product architecture such as API versioning, evolution strategies, rate limiting, and client-adaptive responses. Understand how to maintain backward compatibility, manage API changes effectively, and tailor responses for diverse clients to improve scalability, security, and performance in your API designs.

API versioning

Well-designed APIs aim for stability at the specification level, but evolving requirements and technology inevitably demand changes. Even minor alterations can break client functionality or introduce unwanted side effects. API versioning allows developers to improve their APIs while keeping prior iterations functional. It also gives consumers the freedom to upgrade at their own pace, rather than forcing updates that could break existing applications. For APIs serving billions of users (for example, Facebook's Graph API), forced updates are simply not viable.

Expecting every user to update simultaneously is unrealistic. Versioning gives consumers time to migrate, and it eventually allows providers to deprecate older versions on a defined schedule. Not all changes warrant a new version, however. Understanding which changes do requires grasping the key principles of versioning.

Versioning principles

Since API versioning is an essential part of API design, follow these best practices:

  • A new API version should not break existing clients. Support older versions after releasing newer ones so dependent applications continue to function.

  • Version frequency should be low. Each new version is a significant investment for both providers and consumers. Providers must support multiple versions concurrently, and developers must evaluate the impact on their applications.

  • Prefer backward-compatible changes. If newer code can handle what older versions produced, a new version is unnecessary. Minor additions, like extra query parameters, typically don't break clients and don't require versioning. Rolling out a new version for a non-breaking change wastes resources.

Consider the following client-server version mismatch scenarios:

Both the client and server are on the old version
1 / 4
Both the client and server are on the old version

Four cases illustrate the dynamics:

  1. Both client and server are on the old version: no issues. Versions are compatible.

  2. Server updated, client on the old version: no issues if changes are backward-compatible, since the server can handle calls from older clients.

  3. Both are on the new version: no issues, provided the new version doesn't break the client's application.

  4. Client updated, server on the old version: the server likely cannot handle new API calls unless it is forward-compatibleRefers to versions that remain functional with newer versions., which is rarely the case.

Takeaway: servers are backward-compatible with older clients, but the reverse is not guaranteed.

When to version

Consider a mobile phone API where developers must now return both model and price. This change restructures mobileinfo from a string to an object. Without versioning, the API crashes when it tries to parse an object where it expects a string:

An example of how a small change in the API response can break an application
An example of how a small change in the API response can break an application

To resolve breaking changes like this, roll out a new version with the version embedded in requests so they route to the correct handler. Not every change requires versioning, though. The table below examines various scenarios and whether versioning is warranted in each.

Scenario

Versioning Required?

Example

Minor changes that don't alter functionality

No

Removal of an obsolete entity

Backward compatible changes

No

When the new version on the server-side can process data produced by the prior version

Altering the structure of a resource

Yes

Changing a resource from a string to an object, such as the mobile phone API above

Renaming entities

Yes

Changing an entity from userID to usercredentials

Performance enhancing changes that affect functionality

Yes

Breaking the API into microservices

Twitter illustrates this life cycle well. In August 2020, it released API v2 for early access with improved performance and updated data formats. The standard v1.1 endpoint wasn't retired until June 2021, giving developers nearly a year to migrate.

Versioning approaches

Four popular approaches exist:

  • URL versioning: The most common method. Version information is embedded in the URL as an identifier (e.g., /v1, /v2). Simple and effective, but it carries the highest maintenance cost because a new identifier implies that all resources have changed.

  • HTTP header versioning: The API version is specified via the HTTP Accept header, keeping the URL clean and uncluttered.

  • Hostname versioning: Each version ...