RESTful API design concerns
Tags: rest, api, design, discuss
Published: 2019-07-26 22:42:34

---
title: RESTful API design concerns
published: true
description: Should coupling the API design with system architecture be an issue?
tags: REST, API, design, discuss
---

![](https://thepracticaldev.s3.amazonaws.com/i/lfv7sjpprc9hne7rsd6h.jpg)

_-- Photo by [Omer Rana](https://unsplash.com/@omerrana?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText) on [Unsplash](https://unsplash.com/search/photos/car-park?utm_source=unsplash&utm_medium=referral&utm_content=creditCopyText)_

----------

When working on real production system recently I asked myself a question:

_Should REST API be constrained by the current architecture choices?_

To illustrate the problem I invented an example.
Let's imagine a system which is used for renting cars. The business is sort of Airbnb for "car rental". Small companies which rent cars can register their spot in the system to access wider range of potential customers. The system allows them to manage their cars but not any other rental spot cars.

Let's imagine we're a startup and build the system. We start small and use relational database to store all cars in a single table. Each car is identified by unique ID in this table. 
We want to export a RESTful API for our system.

Among others, we would need APIs to browse all cars in a spot and get single car details.

The API for listing all cars in a spot could look like: 
```
GET /spots/{spotId}/cars
```
It would return a list of cars from which we could get IDs of the cars.


The API for getting a car by ID could look like: 
```
GET /spots/{spotId}/cars/{carId}
```
or
```
GET /cars/{carId}
```

Since we want to be aligned with good practices of API design, we've decided to go with the longer path, because the cars are resources which cannot exist alone and always belong to a given spot. The path `/spots/{spotId}/cars` clearly explains the relationship.

However, the `spotId` in the path is redundant.
Since we have all the cars in single table and we know the car ID, because we got it from the `/spots/{spotId}/cars` endpoint, the only variable we really need is the `carId`.
Of course, in our relational database we will have relation from car to a spot and we could add the `spotId` in out query, but it's not crucial.

E.g. we could have a query like:
```
select c.* from cars c inner join spots s
on s.id = c.spot_id
where s.id = :spotId and c.id = :carId
```
but it would get the same result as: 

```
select * from cars 
where id = :carId
```

So, should we use `/spots/{spotId}/cars/{carId}` or `/cars/{carId}` as the endpoint path?

I've been thinking about it and both options have pros & cons. As mentioned before, the longer one sounds more appropriate from the semantics of the API perspective, but the shorter one is easier to use and implement in the current state of the backend architecture.

If we think about the evolution of our service, then we can imagine that we may want to split the cars table into separate per each spot. This may happen if the volume of data grows, or if we want to distribute database and set several instances in locations nearby to each spot (for better performance and scaling). Each car would then be unique but within the single DB instance (or instances if we consider a cluster of instances in specific location for given spot). Then we could only distinguish a car by a pair of `spotId` and `carId` and the longer API path would make more sense.


Finally, I answered to myself: 
API is not still. When the architecture evolves so does API.
What currently makes sense and is simple (`/cars/{id}`) may not be applicable anymore in future. In future, if I need to split car storage into separate table/database for each car rental spot, the new API may look like: `/spots/{spotId}/cars/{carId}`. On the other hand this might never happen and as Donald Knuth used to say “Premature optimization is the root of all evil”.

What is your answer to the problem. If you have more thoughts please share with me and other readers in comments.