Skip to main content

Error 429: What it means and how to fix it

Your application is running smoothly. Tests have passed. Suddenly you start to see 429 error responses from an API. The 429 error means your app has made too many requests and has hit the rate limit of an API. The 429 (Too Many Requests) error is an HTTP status code is a client error sent back from the server to signal that you've reached your allowed limit.

While rate limiting may seem like a bad thing when you encounter it, this restriction is a protective feature of most consumable APIs. Rate limits prevent services from intentional abuse, as well as accidental abuse that may occur when developers are testing applications. If you've ever poured water into a funnel too quickly, you've seen it start to back up and eventually overflow. Rate limiting aims to prevent this by stopping the flow of requests before a problem arises. You may notice that larger, more widely used APIs like, Instagram or Twitter, have stricter rate limits.

So what can you, as a developer consuming APIs, do about it? To start, let's look at what causes the error and how to find the rate limit details for an API.

Rate limit thresholds and how are they triggered

Depending on the type of application you are building, there are a variety of instances where you may run into rate limiting. Bots, and any application that consistently polls an API, are the most likely to run into the error. Applications that directly let users interact with the third-party API are also at higher risk of hitting limits. Any instance where there is a chance your app has sent too many requests in a short amount of time are subject to this rule. To learn more about an APIs rate limit threshold, it's best to check the documentation for the API you are using.

Normally, rate limits are defined by requests over a period of time. For example, GitHub's v3 REST API has a limit of 5000 requests per hour per authenticated user for authenticated requests. For unauthenticated requests, the limit is 60 requests per hour. These types of limits can either be API-wide, or unique for an endpoint or resource. The Discord API, for example, has unique limits for each endpoint and account. As a result you should avoid hard-coding limits directly into your application.

Another thing to keep in mind is that these time-based limits might be set based on the time of the first request, or may have a fixed timeframe, such as the start of a day.

While many services will publish their limits like in the GitHub example above, others may include limits as a property on responses, or even as a header that only displays when a limit is hit.

Understanding a 429 error response

You've seen the error code, but there's often more information available when your request fails. REST APIs will often include a message describing the problem along with a set of X-RateLimit-* headers with information about the limits. Some APIs, like GitHub's, will include this on successful requests as well. Each API will have their own specific headers, but a few common rate limit related headers are:

  • X-RateLimit-Limit: The amount of requests that can be made (across a time-frame).
  • X-RateLimit-Remaining: The remaining number of requests that can be made (across a time-frame).
  • X-RateLimit-Reset: A timestamp of when the limit will be reset.

GraphQL APIs will either return an error when a limit is hit, like Yelp's GraphQL API, or may instead offer a means to check the current usage. GitHub's v4 Graph API does this by allowing users to query the rateLimit object.

query {
  rateLimit {
    limit
    cost
    remaining
    resetAt
  }
}

These pre-emptive approaches allows you to perform checks before a limit is hit, rather than only reacting to the error.

How to fix the "Too Many Requests" error

If the API provides you with headers or error objects that include reset information, you can use this to wait the appropriate amount of time before retrying. Take the resetAt - currentTime and use that to wait before making another request. You can even bring this functionality into a circuit breaker, or use a solution like Bearer to retry on certain conditions.

If there is no programatic way of knowing how long to wait before trying, you can use the "back-off" approach where your code performs a series of retries with increasing delays between each retry. This way, your code will wait before making a new request at a more realistic interval than immediately repeating on failure.

How to truly avoid 429 errors

These are fine approaches, but what if you are providing an API that is hitting rate limits on other APIs? In this case, you'll want to throttle incoming calls to your API in order to prevent rate limits from causing problems. Throttling is a technique that limits code execution. In this case, requests are limited and "dropped" or fulfilled with cached data. This way your app intervenes before the third-party service ever reaches the limit. This approach can also be useful for restricting usage of costly APIs. You can even implement your own rate limiting with more conservative thresholds that will stop your app from ever hitting the limits of the third-party API.

In order to make more informed decisions, it is a good idea to monitor your third-party API usage. Using a tool like Bearer, you can even set rules to notify you when usage reaches a certain point and react to them programmatically.

With all this in mind, your app should be more resilient against the "Too Many Requests" error. Check the Bearer Blog for more articles on building resilient applications and connect with us @BearerSH to tell us how you respond to 429 errors.

Comments

Popular posts from this blog

4 Ways to Communicate Across Browser Tabs in Realtime

1. Local Storage Events You might have already used LocalStorage, which is accessible across Tabs within the same application origin. But do you know that it also supports events? You can use this feature to communicate across Browser Tabs, where other Tabs will receive the event once the storage is updated. For example, let’s say in one Tab, we execute the following JavaScript code. window.localStorage.setItem("loggedIn", "true"); The other Tabs which listen to the event will receive it, as shown below. window.addEventListener('storage', (event) => { if (event.storageArea != localStorage) return; if (event.key === 'loggedIn') { // Do something with event.newValue } }); 2. Broadcast Channel API The Broadcast Channel API allows communication between Tabs, Windows, Frames, Iframes, and  Web Workers . One Tab can create and post to a channel as follows. const channel = new BroadcastChannel('app-data'); channel.postMessage(data); And oth...

Certbot SSL configuration in ubuntu

  Introduction Let’s Encrypt is a Certificate Authority (CA) that provides an easy way to obtain and install free  TLS/SSL certificates , thereby enabling encrypted HTTPS on web servers. It simplifies the process by providing a software client, Certbot, that attempts to automate most (if not all) of the required steps. Currently, the entire process of obtaining and installing a certificate is fully automated on both Apache and Nginx. In this tutorial, you will use Certbot to obtain a free SSL certificate for Apache on Ubuntu 18.04 and set up your certificate to renew automatically. This tutorial will use a separate Apache virtual host file instead of the default configuration file.  We recommend  creating new Apache virtual host files for each domain because it helps to avoid common mistakes and maintains the default files as a fallback configuration. Prerequisites To follow this tutorial, you will need: One Ubuntu 18.04 server set up by following this  initial ...

Working with Node.js streams

  Introduction Streams are one of the major features that most Node.js applications rely on, especially when handling HTTP requests, reading/writing files, and making socket communications. Streams are very predictable since we can always expect data, error, and end events when using streams. This article will teach Node developers how to use streams to efficiently handle large amounts of data. This is a typical real-world challenge faced by Node developers when they have to deal with a large data source, and it may not be feasible to process this data all at once. This article will cover the following topics: Types of streams When to adopt Node.js streams Batching Composing streams in Node.js Transforming data with transform streams Piping streams Error handling Node.js streams Types of streams The following are four main types of streams in Node.js: Readable streams: The readable stream is responsible for reading data from a source file Writable streams: The writable stream is re...