REST API Design: 4 Tips You should Start Applying to your ML Engineering Project
A glimpse of what I’ve learnt about REST API design, and how I think these learning points can be applied to Machine Learning (ML) Engineering
When I started my first ML engineering project in my current team in SAP, I had no idea that this thing called API design existed. Sure, I went through some tutorials for FastAPI, and could start up a REST API server to handle model inference requests from end users, but there wasn’t much emphasis on API design back then (probably because there wasn’t really any need to).
As my team started shifting our sights on the ease of use of our applications, the need to develop frontend UIs came. That was when the lack in proficiency of API design became obvious. Our APIs had endpoints to allow users to perform model inference, but suffered from issues such as poor naming of endpoints, not knowing when to use a request body instead of a query parameter, and lack of API documentation.
These were not big concerns previously, as there weren’t that much work on frontend back then. Even if there were, everyone was still working in the office, so one colleague could just quickly clarify any doubts they might have about the API with whoever worked on it. However, in the recent years, our work arrangement had transited to the hybrid model, where everyone could choose either to work in office or at home. Because of this arrangement, ambiguous APIs could result in more effort, as colleagues might have to schedule calls just to clarify any doubts they might have about the APIs.
As such, some colleagues felt that following best practices for API design could greatly reduce the amount of back-and-forth communication needed to be clear about the API. With this pain point in mind, I decided to do some learning about REST API design as this was a pretty new area for me.
Cool Things I’ve Learnt about REST API Design
My main resource for learning about REST API Design was this book titled “A Practical Approach to API Design: From Principle to Practice” by D. Keith Casey Jr and James Higginbotham. I found this book quite comprehensive, learning about many things I never really knew about when it came to REST API design. Of course, since the authors were writing from the viewpoint of a developer who works on products like Twilio or SendGrid (where the APIs are the only products), some points that they mention might not really apply to ML Engineering (where the APIs are not the only products). Having said that, there are still nuggets of information within the book that could definitely help us when creating our APIs for model inference.
Besides the REST API design book, I’ve also referred to other resources such the documentation for OpenAPI to learn more about how API documentation is done, and the documentation for FastAPI, which is gaining popularity among developers who work with the Python language.
With that out of the way, let’s see how we can start using these learning points about REST API Design.
1. Using the Most Appropriate HTTP Status Code for each Endpoint
The HTTP status codes that are already out there are defined in RFC 9110: HTTP Semantics, and is the standard used by all API developers (except for the mavericks I guess). As such, the authors of the REST API design book discourage developers from inventing their own status codes, to avoid any confusion due to the API user not understanding these custom status code.
Although a developer could just decide to use status code 200 (OK) for successful response from all their endpoints, it is typically better to check the definitions of the status codes in RFC9110 and use the one that best suits the task performed by every endpoint.
For example, if an endpoint does the writing of data to a database, the recommended status code would be 201 (Created) rather than 200, to indicate that a new resource (i.e. data) has been created successfully. If we have another endpoint that is intended to delete some data, the recommended status code would be 204 (No content), to indicate to the user that no response is expected (which makes sense for delete operations since there’s nothing left to return as response).
This applies to the status codes for failures as well. As a general rule of thumb, 4xx status codes indicate errors on the part of the client (user messed up), while 5xx status codes indicate errors on the part of the server (server messed up). Using the 4xx/5xx status code that best suits the error that could potentially occur will be a great help in narrowing down of the potential causes during debugging.
2. Using the Right HTTP Verb for each Endpoint
Those who have created endpoints for the APIs they’re working on would have seen these:
DELETE. These verbs describe the categories of tasks that each endpoint is expected to perform, and there are some guidelines on how to select the most suitable verb for each endpoint.
According to the REST API design book, generally:
GET: Retrieves a specific collection or resource, e.g. fetching data from a database
PUT: Updates a resource at the specified URI, e.g. replacing an entire database table row with a new one
PATCH: Updates a partial resource at the specified URI, e.g. updating one or more values in a database table row
DELETE: Deletes the specified resource, e.g. deleting a row in a database table
POST: Creates a resource as described, or modifies the underlying state of the system, e.g. inserting a new row to a database table, running some model inference
DELETE are recommended to be used strictly only for retrieving, updating or deleting resources respectively,
POST is more generic and can be used for any task that doesn’t fall into the other 4 categories.
As with HTTP status codes, the authors of the REST API design book discourage developers from creating their own HTTP verb for their endpoints, as most HTTP client libraries are not able to handle arbitrary verbs.
3. Modeling your API
As of this writing, I’m working on an ML project that someone else had worked on for a while but wasn’t able to continue. That colleague had created some endpoints for the backend API, some of which handle CRUD operations for the data used, while some were used for doing model inference. When I was trying to make modifications to some of the endpoints for the CRUD operations, I realized that some of the endpoints they created had some flaw in the logic which hadn’t been caught earlier. The authors of the REST API design book give significant emphasis on API modeling, which could potentially catch some of the logic flaws before actual implementation of the API, and I thought this was what was lacking for the project.
The goal of API modeling is to fully understand and validate the requirements of the developers and end users. The authors of the REST API design book list the following 5 steps to help identify the requirements of our API design:
- Identify the participants, or actors, that will interact with the API
- Identify the high-level activities that participants wish to achieve
- Separate the activities into steps that the participants will perform
- Create a list of API methods from the steps, and group these into common resource groups
- Validate the API by using scenarios to test the completeness of the API
As there are quite a lot of details regarding API modeling, I will definitely recommend either reading the REST API design book for completeness, or the article titled “Before you design your API, model your API” by James Higginbotham if you’re only interested in reading about API modeling. Whichever the case, I agree with the authors’ recommendation to spend some time and effort doing API modeling.
4. Using FastAPI for API Development
Besides API modeling, the authors of the REST API design book also describe other tasks of the API development, such as the API documentation and prototyping of APIs. In many cases, the prototyping and documentation are separate, mainly due to the framework(s) used for both of these tasks. However, I’ve discovered that FastAPI could enable developers to do documentation and prototyping within the same framework, which makes development much more convenient.
To be clear, the authors of the REST API design book never mentioned anything about using FastAPI. This is likely because the book was published in Jan 2019 while FastAPI was first released in Dec 2018, so the authors might not have known about FastAPI while they were writing the book. However, I thought I would bring in FastAPI here, as there are some benefits to using this framework:
- FastAPI is meant for the Python language, which makes it much easier when developing APIs for ML Engineering projects as Python is the most commonly used language for ML
- FastAPI has excellent support for documentation. FastAPI uses the OpenAPI specification for documentation, which is one of the standards recommended by the REST API design book. FastAPI also comes with the feature to automatically generate a Swagger UI for trying out the endpoints, as well as a Redoc UI which in my opinion makes API documentations look cool.
- FastAPI has a good balance between the ease of API development and performance in production. As such, it is a good choice for creating evolutionary prototypes, i.e. prototypes that could be built on to eventually form the actual products
FastAPI has comprehensive documentation on how to do API documentation with Pydantic models and specific FastAPI functions, so I would recommend checking out the FastAPI documentation to find out how to do all these.
These tips that I’ve shared so far are some of the learning points that I find quite applicable to ML Engineering, but there is way more good content in the REST API design book than what you’ve seen so far. Therefore, I would highly recommend giving the book a read if you’re serious about doing REST API design the right way. I’ll also love to hear more about what you think in the comments. Have fun with designing 😃