How to Create a Bad REST Service: A Quick Guide

REST API is one of the most popular types of web services. But despite the many tutorials on how to create it, in practice there are services that only cause disappointment among users.

This prompted Kostya, a project developer at Naumen, to create a short guide to writing bad REST service. For several years now he has been supporting and developing projects on the Naumen Service Management Platform, often encounters REST API design and knows exactly what mistakes are best to avoid.

Kostya Latyshov

Senior Developer at Naumen Service Desk

In the article, Kostya shared the main anti-patterns and said that there is no need to carry them into production.

REST API: what is important to know

REST API is an architectural style that defines how the server should interact with the client. Although many people confuse it with HTTP, REST is not a data transfer protocol. The service may run over HTTP, but that does not make it a REST API.

To be called a REST API, a service must meet certain architectural requirements:

  • client-server model;

  • lack of condition;

  • caching;

  • uniformity of the interface;

  • multi-level system;

  • code on demand (optional);

  • resource management (we address not the service, but the resource).

For myself, I highlight two key requirements for the REST API. The first is lack of condition. The service should not store information between requests. It gets everything it needs to process the request directly from the request itself. The second one is correct resource management. It is important how the URLs are formed, what HTTP methods are used, and how the responses are structured. This directly affects the ease of use of the service.

This approach should use nouns in URLs to identify resources and verbs in HTTP methods such as GET or POST to help clients integrate with the service faster and avoid confusion.

How to Identify a Good REST Service

Before we talk about how to make a bad service, let’s consider several important characteristics for a REST service that will help you understand that we have a good service:

  1. Understandability. The client should easily understand how to access the service and what he will receive in response.

  2. Compliance with REST principles. The service must adhere to REST principles so that the client understands how to work with it.

  3. Safety. Access to the service should be limited to prevent data leakage and unauthorized access to confidential information.

  4. Performance. Requests must be processed quickly, without long delays.

Bad advice: how not to make a REST service

Now that we've discussed what a good REST service should look like, let's look at what needs to be done to make it “bad”. Below I share four bad tips.

Bad advice #1: We destroy resource management

What principles to follow
  • The URL should describe in detail what the client wants to do – the more confusing and longer, the better 🙂

  • For all operations we use POST

  • if the request has been received, we send 200 OK – it has arrived, it means everything is in order

In a bad REST service, the URL should not be associated with any resources. Ideally, he should simply describe what will happen as a result of processing the request. This way the client will “understand” what to do and what will happen. True, there is a downside – it is easy to make a typo in such a URL, but since we are making a bad service, this is not so critical.

As for HTTP methods, in poor service only POST requests are used. After all, POST allows you to transmit the body of the request, and there you can already specify everything that is needed to process it.

Another important rule for a bad REST service is minimize the number of response codes. Usually, 2-3 response options with code 200 are enough. For example, 200 means the request was received, and 500 means an error when something went wrong. What exactly happened? It doesn’t matter – the logs will always help you figure it out.

An example of a bad API is Twitter API v 1.0which ceased to exist in 2007. Many remember it as inconvenient and confusing. There were four methods in the documentation, and no one really understood what they did:

  1. The first method returned all the user's tweets.

  2. The second, despite the name “update,” allowed the creation of new tweets.

  3. The third method deleted tweets.

  4. The fourth returned a tweet feed for an authorized user.

Since then, Twitter has moved to version 2 of the API, which works like a normal REST service, with a clear and intuitive structure.

Bad advice No. 2: forget about storing your fortune

What principles to follow

Save the state of requests. Let the service “remember” everything:

Bad REST service must store state. One example is sessions. We log in, get the session identifier, save it in a cookie, and then the service “knows” us. All subsequent requests proceed without the need for re-authorization. On the one hand, this is convenient, because the client does not need to send authorization data every time. On the other hand, this creates a lot of scaling and security problems.

Let's say the number of users of the service has increased, and we decide to add a second REST service to distribute the load. Let's set up balancing of requests so that even requests will go to one instance, and odd requests to another. The problem is that if sessions are not replicated between servers, the user will only be logged in to one of them.

This can lead to unpredictable behavior and increased response time when the server reports that the user is not authorized, although just a few minutes ago he was successfully authorized on another server.

Bad advice No. 3: ignore encryption during authorization

What principles to follow

In a bad REST service no encryption needed. Why spend money on certificates and certification authorities? You can use the simplest authorization – Basic Authenticationin which the username and password are sent in the request header, encoded in Base64. There is no encryption, but the service appears to be secure. However, there is a caveat: if an attacker intercepts the traffic, he can easily decrypt the data.

Example: the user is working from a public network, and the attacker is using a traffic interception application such as Wireshark. He sees our credentials and uses them for unauthorized access to the service.

What does an attacker see when there is no encryption?

What does an attacker see when there is no encryption?

If we applied encryption, for example, through TLSthe data would be protected, and the attacker would only see the encrypted set of characters.

What does an attacker see when there is encryption?

What does an attacker see when there is encryption?

Bad advice #4: block threads

What principles to follow
  • the user likes to look at the red loading indicator

  • blocking threads is a way to feel like a real programmer

  • asynchrony is for weaklings

Blocking threads directly affects the performance of the service. Here's what's important to remember:

Scaling

Performance problems can occur when requests begin to process more slowly. This happens when the service begins to degrade due to an increase in the number of users. In such cases, scaling helps – you can add another instance to the cluster to distribute the load. This way, the load is balanced across instances, which improves overall performance.

Asynchronous execution of operations

Another common situation is when a service sends data to an adjacent, internal or external, service that takes too long to process the request. In such cases, it makes sense to make the operation asynchronous. This means that the client will receive a response that the operation has been accepted for execution, and the task itself will be executed later, for example, through a queue. You can return an ID to the client to track the progress of the operation. If tracking is not required – as in the case of sending notifications or letters – you can not return anything at all.

Non-blocking calls

Performance may also degrade if blocking calls are used. There are a limited number of threads that process HTTP requests. If they are all busy, a situation arises where “threads have run out.” To avoid this, it is important to use non-blocking calls that free up threads for other operations.

But for a bad REST service blocking calls are what you need. All HTTP threads will be busy performing tasks, and at this time the user will look at the loading indicator. To do this, you should use blocking methods that occupy threads and force other requests to wait their turn.

How do the methods differ? blocking And non-blocking? Both use two threads to process requests. However, the method non-blocking has additional four threads – executor threadswhich do the bulk of the work, freeing up HTTP streams for other requests.

When using the method blocking threads go to sleep for 10 seconds, blocking the ability to process other requests during this time.

In the case of the method non-blocking The HTTP thread processing the request passes the task to the thread pool – thread poolcontaining four executor threads. One of the free threads will take the task for execution, and the HTTP thread will be freed to process new requests.


Mistakes in the design of a REST service can seriously impact its performance, security, and usability. These bad tips clearly show what to avoid when developing APIs to make the service reliable, convenient and safe for users.

If you want to understand the topic in more detail, I recommend watching the recording of my report from the Naumen Java Junior Meetup for beginning developers.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *