In 2002, Jeff Bezos issued a mandate to all Amazon development teams that included the following statements:
- “All teams will henceforth expose their data and functionality through service interfaces.”
- “Teams must communicate with each other through these interfaces.”
- “There will be no other form of inter-process communication allowed…”
- “All services, without exception, must be designed from the ground up to be externalizable. That is to say, the team must plan and design to be able to expose the interface to developers in the outside world. No exceptions.”
The two major takeaways from this mandate are:
- Services must integrate with each other via API calls
- APIs should be initially designed to be externalizable
While these statements were made with good intentions for Amazon 17 years ago, I’ve since seen many other companies follow this mandate blindly and without experience, which has caused major issues with their technical architecture. Bezos probably realized that public APIs were going to be a major competitive advantage for years to come, which has proven to be true. Additionally, he was incorporating the “eat your own dog food” strategy within his own organization by requiring dev teams to use the same APIs that are exposed to the outside world. Executives that have seen the rise in popularity of public APIs and realize the success of Amazon are implementing a similar mandate within their own organizations. However, public APIs are built specifically for other people, so it’s very important to understand who the other users are and what their needs may be. Blindly building the “Bezos way” can also reduce your velocity in developing new features, slow down or cripple your system, and negatively impact users/customers. Jeff Bezos is not a technical architect, but his mandate has affected the architecture of software products. In order to realize the benefits that Bezos originally intended when building a public API, you must first consider the following.
Pitfalls of instituting all synchronous API calls
The Bezos mandate calls for synchronous communication between services with API calls, with no other form of communication allowed. There are times when it makes sense for a service to interact with another service through an API call, but that introduces a level of coupling between the services. What happens when one of the services is down, or the service is overloaded and slow to respond? The calling service is also going to be slow to perform because of the service it’s making an API call to, which usually means that the user will have a negative experience. This can cause a ripple effect across the application, especially when you consider the number of services and the number of API calls that might need to be made to fulfill a user’s request. In his video “Avoiding Microservice Megadisasters,” our Chief Architect Jimmy Bogard provides a detailed account of the perils of relying purely on synchronous API calls.
There are other integration patterns that should be considered for communication between services. Asynchronous messaging, for example, enables services to become more autonomous. This autonomy is key to building a resilient distributed system and is fundamental to a microservices architecture, as it protects the entire system from being affected when one of its parts is having issues. Asynchronous communication is not the answer to all service interaction use cases, but it should definitely be considered when architecting a system.
Designing APIs to be externalizable
The second part of the Bezos mandate calls for development teams to design an externalizable interface from the beginning. Exercise caution when following this recommendation. Forcing product managers and developers to design for the external use case that might happen instead of designing to solve the immediate problem will take additional time and could lead to a less-than-ideal implementation. External APIs should be designed to support multiple different UIs and use cases, in order to increase the number of companies that benefit from them. On the other hand, internal APIs are built for a specific UI and use case to streamline the interactions. At a minimum, you should build your application in a way that it will be easy or expose or create public APIs when the need arises, as opposed to forcing teams to reverse engineer the code base.
There are certainly cases in which it makes sense for a company to build an API that will be exposed to other organizations and developers. It can be a major competitive advantage in that it allows other applications to integrate with your product, or you can sell licenses to use the API. However, if your API strategy isn’t well thought out and executed, then your clients may lose trust in your product and company.
Building a public API that people can (and want to) use
When building a public API, you need to keep in mind that the developers using it will probably have limited knowledge of your system and domain. These external developers are your end users and you should consider them in all decision-making. It should be your goal to make the API as easy to understand and develop against as possible. Otherwise, no one will want to use it. Before releasing your API to the public, these are the three key strategy points you need to consider:
- Sandbox Environment
Having comprehensive and easy-to-understand documentation is the cornerstone of a good public API—it’s often the first thing people look for when choosing to integrate with a system. If the documentation is lacking, it’s less likely that developers will want to work with your APIs, so you could lose that potential business.
At minimum, public API documentation should include the following:
- Getting started: A page that provides an overview of the API and includes information such as common use cases, first steps, an overview of the authentication/authorization approach, etc.
- Overview of each endpoint: A few sentences explaining what the API should be used for. It needs to make sense to developers, business analysts, and product managers alike. Additionally, all parameters that can be included should be listed, with a description of what the parameter effects.
- Sample requests/responses: Each endpoint that you have documented should include all of the fields that are supported in the API, with sample data for each field. It’s also beneficial to have a description of each field and its validation rules.
- Grouping of similar APIs. If there is a set of APIs that are usually used in conjunction with each other for a similar set of functionality, they should be grouped together in the documentation page. This will make it easier to understand how the APIs should be used, without having to scroll all over the page to figure it out.
Teams can use tools such as Swagger to automate the creation of API documentation. This reduces the amount of overhead required for documentation and integrates it into the development process.
Consistency across endpoints should be another key element of your public API strategy, especially in a few key areas. For example, it’s very frustrating for an external developer to have to refer to the documentation for every endpoint to see how pagination is implemented, and then have to change his or her implementation endpoint-by-endpoint.
Collaborate on and document these standards to ensure that they are well understood throughout the organization. Keep in mind that different teams might be developing each endpoint based on the area of the application that they are responsible for. That’s why it’s important to document standards and preach consistency throughout the development of your API.
Some of the key API elements that require consistency are:
- Pagination: APIs that return a large set of results should be paginated for performance. The default page size should be consistent across endpoints, so the same number of results are returned when page size is not specified. Additionally, the way that developers specify the page to return and the number of results to return per page should be consistent across endpoints.
- Response codes: There should be a standard set of success and error codes that are consistent across all endpoints and the response body should include the same amount of detail across the endpoints when an error occurs.
- Nouns vs. verbs: The majority of RESTful API documentation states that endpoints should be noun-based and the action that is taken should be handled as part of the HTTP verb (POST, GET, PUT, PATCH, DELETE). However, APIs can be easier to understand when verbs are allowed to be endpoints (aka “action endpoints”). Regardless of the route you choose, be consistent.
- PATCH support: The PATCH action allows only certain fields of a resource to be sent and updated in the HTTP call, as opposed to a PUT which requires all fields to be sent. The decision to support PATCH should be made at the organizational level and apply to all or none of the endpoints.
The last key to building an API that people want to use is to provide an easy way for developers to quickly make API calls against a test or sandbox environment. This will require additional documentation that specifies how to use the test environment or tool. Additionally, the environment will need to be created and populated with relevant test data, and that data will need to be maintained.
As mentioned earlier, documentation is great, but some people prefer to learn and absorb information with a hands-on approach. There are two standard ways to provide access to a sandbox environment to external developers:
API documentation tool: The majority of API documentation tools, such as the previously mentioned Swagger, provide the ability to make API calls directly from the documentation. This approach allows developers to quickly make actual calls and observe how changing the different parameters affects the responses.
An environment with test credentials: Some companies choose to provide test environment and credentials to be able to make API calls either programmatically or with a tool such as Postman. This requires slightly a slightly deeper technical knowledge than using an API documentation tool, but it allows developers to understand exactly what will need to happen to make the API calls.
The key to a public API strategy is to build something that developers want to use, by making them accessible, usable, and testable.
Building a public API the Bezos right way
APIs, and specifically public APIs, can be a major competitive advantage for software companies. Allowing other organizations to integrate with your systems can expand your reach and bring in revenue. However, careful thought should be put into why, how, and when the public APIs should be developed because they can have negative implications for your product and business if implemented incorrectly.