Serving up a Microservice API: naming
Posted on June 8, 2016
In my last post, I described a microservice as a set of web API endpoints. When implementing a microservice framework then, our most fundamental task is to provide those endpoints. There are a number of things to consider, and one of the first steps is to decide what and how the endpoints are called.
What is an API endpoint again?
An API endpoint is just a URL that can be called from a web client such as a browser application. Unlike a web site like http://www.homedepot.com that returns interactive visual content, an API endpoint performs some specific action or answers a question with structured data.
Some example API endpoint URLs might be:
/services/product/getAll /services/product/get /services/product/add
When a web server receives a request URL that represents a web page, the server follows a predefined set of rules to decide which HTML file to send back to the caller. When a web server receives a request URL that represents an API endpoint, it executes the code that performs the desired action or query, returning data in a form usable by a calling program. The server uses the form of the URL itself to determine if the the request is for web page content or for an API action. For example,
refers to web page content, but
might be an API endpoint (it isn’t really).
We’d like a present an organized view of our URLs that represent API endpoints. Providing a meaningful, well-named hierarchy of endpoint URLs helps developers make sense of our API without having to resort to documentation that is likely to become out of date over time.
The example endpoints above give you a general sense of what an endpoint hierarchy might look like. Let’s take a closer look at one of our real-world microservice endpoints:
This URL is a little more complicated than the earlier examples. It has a number of meaningful elements:
This is the root of all of our API endpoints. Having a common starting segment in the URL helps us route all API requests to a common middleware handler on the web server. Note also that there is no hostname at the beginning of the URL. This a relative URL endpoint, which means that the microservice is hosted on the same server as the calling web application, and the web app can issue an ajax call to use this endpoint without concern for cross-domain browser security constraints.
This is the name of the microservice hosting the API endpoint. This is important because our endpoint names and categories might be relatively generic. By including the microservice we can differentiate between API operations that have the same name but are hosted by different services.
This is the version of the microservice needed by the caller. There are different versioning schemes, but in our framework we use semantic versioning, which expresses API compatibility between versions. This URL could be routed to different versions of the same microservice; versions 1.0.0, 1.0.1-build-7 and 1.9 would all match this request. Version 2.0.0 of the service could not satisfy the request. Including a version in the endpoint URL also opens up the possibility of running multiple versions of an API simultaneously.
This is the domain (i.e. category) of the API. Our implementation is based on domain-driven design, so Issue represents a specific domain in our business. The API endpoint is an operation on an Issue domain entity. More about this later – for now just think about domain as a category of APIs that cluster around a specific business concept.
This is the specific API operation that will be performed when the the endpoint is called. In this case, we are resolving a system operation issue.
From the information in these URL elements, the web server has enough knowledge to decide which microservice API should be executed.
In my next posts, I’ll talk about how we pass input arguments to the microservice API, how we invoke the API code, and how we communicate results back to the caller.