Always use a timeout for http requests

Abu Ashraf Masnun
3 min readJan 30, 2019

--

Depending on the nature of our applications, we probably have to make from a few to a lot of http requests. Many third party services we use in our apps provide APIs to be accessed over http. And in consuming them, while making those http requests, we should carefully set a timeout.

By setting a timeout, we’re basically saying, if the server doesn’t respond within this time, I can no longer keep waiting for it to respond, let’s move on. Our destination servers can become slow and non responsive for many reasons. May be they are hitting resource cap? May be they are too busy processing other requests? Waiting for them to respond can sometimes cause disaster.

Let’s say we have a SMS marketing system where we fetch offers from a remote service and send SMS promos to our users. We put the users in a queue and process the queue over time. What if the third party service takes forever to respond? If we don’t have a timeout set, our entire system becomes stalled. Even if it’s not fully stuck, the service is just too slow, that too could accumulate a lot of tasks on your queue — the queue will grow faster than you can drain it — ultimately ending in a disaster.

Having a timeout helps in such cases, when a timeout is triggered, you can report an error, set a retry policy or intelligently fall back to another service. A timeout saves you from a disaster and gives you control over how to handle such issues.

Demo

Let’s create a sample Flask api that never responds.

A flask app that blocks indefinitely

If we run the above code, it should never send the response. The infinite while look makes sure of that.

Now let’s try making requests.

If we run the above code, we will notice that the first request gets stuck. It never completes.

Let’s use timeout. We’re using the excellent requests library in Python. It allows us to pass a value for timeout argument in seconds. If the target server hasn’t responded within this period, it raises an exception.

We’re setting a timeout of 1 second. We’re also explicitly handling the Timeout exception. We can match this exception to detect if it was a timeout issue or some other errors occurred and then decide how to gracefully handle this incident.

The output this time would look like this:

Making first request
Exception Raised: HTTPConnectionPool(host='localhost', port=8000): Read timed out. (read timeout=1)
Making second request
Exception Raised: HTTPConnectionPool(host='localhost', port=8000): Read timed out. (read timeout=1)

All production code should explicitly set a timeout. While testing out a service, it might seem like they’re responding fast and they’re less likely to fail, but trust me, the unexpected does happen. Being careful beforehand will save you a lot of trouble along the road.

--

--