{"id":27347,"date":"2023-01-05T11:21:10","date_gmt":"2023-01-05T19:21:10","guid":{"rendered":"https:\/\/coderpad.io\/?p=27347"},"modified":"2023-06-05T13:46:43","modified_gmt":"2023-06-05T20:46:43","slug":"a-guide-to-api-rate-limiting-in-django","status":"publish","type":"post","link":"https:\/\/coderpad.io\/blog\/development\/a-guide-to-api-rate-limiting-in-django\/","title":{"rendered":"A Guide To API Rate Limiting In Django"},"content":{"rendered":"\n<p>Imagine you&#8217;re driving on a busy highway during rush hour. As you approach a bottleneck in the road, you start to slow down and eventually come to a complete stop. Suddenly, a car comes speeding up behind you and tries to squeeze into the small gap between you and the car in front of you. The driver behind you is trying to bypass the traffic and get ahead, but their reckless behavior could potentially cause an accident. This is similar to the concept of rate limiting in the digital world. Just like how a bottleneck on a highway limits the number of cars that can pass through at a given time, rate limiting in technology limits the number of requests a server can handle in a specific timeframe to prevent overwhelming traffic and potential crashes.&nbsp;<\/p>\n\n\n\n<p>API rate limiting is one of the most effective practices for improving security and preventing large spikes in API request calls, which can degrade overall performance.<\/p>\n\n\n\n<p>In this article, we will discuss rate limiting and why it is essential, different types of rate limiting, rate-limiting implementation methods, and how we can implement throttling in Django.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Objectives<\/h2>\n\n\n\n<p>By the end of this article, we should learn the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>Rate limiting and why it is important&nbsp;<\/li>\n\n\n\n<li>Different types of rate limiting&nbsp;<\/li>\n\n\n\n<li>Methods of implementing rate limiting&nbsp;<\/li>\n\n\n\n<li>How to implement rate limiting in Django&nbsp;<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">What is rate limiting and why is it important?<\/h2>\n\n\n\n<p>Rate limiting is a technique used to control or limit the distribution or flow of traffic on an API in order to keep it from becoming overloaded and underperforming. API owners typically impose some control over their APIs by limiting the number of requests in a given time frame to ensure that clients use their resources fairly. This avoids an unnecessary spike in its traffic and improves web service scalability.<\/p>\n\n\n\n<p>When developing applications with many users, API rate limiting is essential. It limits bot attacks to APIs and prevents <a href=\"https:\/\/www.paloaltonetworks.com\/cyberpedia\/what-is-a-denial-of-service-attack-dos\" target=\"_blank\" rel=\"noopener\">DoS attacks,<\/a> in which a user launches many requests in seconds. Rate limiting can be used to ensure that API resources are not depleted and that legitimate users have proper access to the API.<\/p>\n\n\n\n<p>Rate limiting is measured in requests per second, or RPS, which means that we can, for example, configure our API to allow three requests per minute from a specific user. When the user exceeds the limit, the API returns a <code>429<\/code>&nbsp; status code error, which means &#8220;Too Many Requests,&#8221; to notify the user that they have sent too many requests in the allotted time frame.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2023\/01\/img_63b6f40378cab.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">A server rate limiting requests<\/figcaption><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Types Of rate limiting&nbsp;<\/h2>\n\n\n\n<p>Rate limiting can be used by defining different parameters based on the objectives and level of restriction desired. There are three major types of rate limiting, which we will go over in more detail below.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">User rate limiting<\/h3>\n\n\n\n<p>This type of rate limiting detects the number of requests made by a specific user and limits the user based on the restrictions set by the API developer. Many organizations use it as the most common type of rate limiting. It typically monitors a user&#8217;s IP address or API key and blocks additional requests if the limit is exceeded within the time frame specified until the rate-limiting period resets.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Geographic-based rate limiting<\/h3>\n\n\n\n<p>This type of rate limiting limits the number of requests sent to the server from a specific region and location. This can be useful for reducing traffic spikes from a specific region, freeing up resources in the target regions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Server rate limiting<\/h3>\n\n\n\n<p>If different servers handle different parts of an application, rate limiting can be configured at the server level. This method allows developers to increase the rate limit on frequently used servers while decreasing the traffic limit on less regularly used servers, giving them more flexibility.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Different methods of implementing rate limiting<\/h2>\n\n\n\n<p>Rate limiting can be implemented in various ways in an application. Below, we will go over some of the more general methods.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Using request queues<\/h3>\n\n\n\n<p>Request queues limit the number of requests sent to an API in a given time frame. It is one of the most commonly used rate-limiting techniques. Numerous request libraries are available for various programming languages that make it simple to set rate-limiting for our API while doing most of the hard work for us. Service services such as Amazon Simple Queue Service can handle request and message queues.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Throttling<\/h3>\n\n\n\n<p>Throttling is the process of putting the API into a temporary state to evaluate each request. A user may be disconnected or have a slower bandwidth when the throttle is triggered. It is a flexible rate-limiting method that can be applied at the user, API, or application level.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Rate limiting algorithms<\/h3>\n\n\n\n<p>There are several algorithms to use when implementing rate limiting in a system. We will be discussing some of them below:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Leaky Bucket:<\/strong> Leaky Bucket is a memory-efficient algorithm that queues and processes user requests using the FIFO (First In, First Out) method. It creates a queue with a specific capacity in a given time frame, processes each request in the queue in the order they arrive, and discards requests that arrive when the queue reaches its capacity in the given time frame. The leaky bucket algorithm makes it simple to regulate API requests and avoid traffic outbursts or spikes.<\/li>\n<\/ul>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><img decoding=\"async\" src=\"https:\/\/d2h1bfu6zrdxog.cloudfront.net\/wp-content\/uploads\/2023\/01\/img_63b6f4054cb0f.png\" alt=\"\"\/><figcaption class=\"wp-element-caption\">leaky bucket algorithm for rate limiting<\/figcaption><\/figure>\n<\/div>\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Token Bucket<\/strong>: Token Bucket is an algorithm that tracks individual users and the number of requests they make in a given period to limit them based on the quota set by the developer. When a user makes a request, the bucket containing the number of tokens the user has in the given time frame is checked, and if there are enough tokens, the request is processed, and a token is removed from the bucket. When the bucket&#8217;s tokens are depleted, the incoming request is rejected until the rate limiter is reset.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Fixed window<\/strong>: Each user&#8217;s requests are given a fixed time window of n seconds in this algorithm. When a user requests within a specific time frame, a counter is incremented to keep track of how many requests the user is making. When the counter reaches the maximum number of requests for each window, the requests are discarded and not processed.<\/li>\n<\/ul>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Sliding window<\/strong>: This algorithm is similar to the fixed window algorithm, but the individual requests for a timestamp are not saved in this case. The sliding window will keep timestamps and a counter for requests that occur at the same time. This aids in the management of bursts of requests that occur at the same time and saves memory space.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\">Implementing throttling in Django<\/h2>\n\n\n\n<p>Throttling is the same as permissions in the <a href=\"https:\/\/www.django-rest-framework.org\/\" target=\"_blank\" rel=\"noopener\">Django Rest Framework<\/a>, as it determines whether a particular request should be authorized or discarded. It is used to rate-limit the number of API requests a client can make. Throttling is flexible in DRF, and multiple throttles can be implemented to control requests made by authenticated and anonymous users or to restrict resources based on different parts of the APIs.<\/p>\n\n\n\n<p>Now let\u2019s create an API and set some throttle policies.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Project setup<\/strong><\/h3>\n\n\n\n<p>To get started, we will set up a new <a href=\"https:\/\/app.coderpad.io\/sandbox\" data-type=\"URL\" data-id=\"https:\/\/app.coderpad.io\/sandbox\">CoderPad Django sandbox<\/a>. In the sandbox shell, install the <code>djangorestframework<\/code> library:<\/p>\n\n\n<pre class=\"wp-block-code\"><span><code class=\"hljs shcb-wrap-lines\">$ pip install djangorestframework<\/code><\/span><\/pre>\n\n\n<p>We then add the new app and <code>rest_framework<\/code> to the list of installed apps in <code>settings.py<\/code> and create a <code>urls.py<\/code> file for the app.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\">INSTALLED_APPS = &#91;\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">\"django.contrib.admin\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">\"django.contrib.auth\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">\"django.contrib.contenttypes\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">\"django.contrib.sessions\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">\"django.contrib.messages\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">\"django.contrib.staticfiles\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">\"productApp\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">\"rest_framework\"<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">\"rest_framework.authtoken\"<\/span>,\u00a0\u00a0\u00a0\u00a0\u00a0\n\n]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We will be having two <code>urls.py<\/code> files, one will be included in the project\u2019s directory while the other in the <code>productApp<\/code> folder. Let\u2019s create a new <code>urls.py<\/code> in the app\u2019s directory and include it in the project\u2019s own.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> django.contrib <span class=\"hljs-keyword\">import<\/span> admin\n\n<span class=\"hljs-keyword\">from<\/span> django.urls <span class=\"hljs-keyword\">import<\/span> path, include\n\nurlpatterns = &#91;\n\n\u00a0\u00a0\u00a0\u00a0path(<span class=\"hljs-string\">\"admin\/\"<\/span>, admin.site.urls),\u00a0\n\n\u00a0\u00a0\u00a0\u00a0path(<span class=\"hljs-string\">\"products\"<\/span>, include(<span class=\"hljs-string\">\"productApp.urls\"<\/span>))\n\n\u00a0\u00a0\u00a0\u00a0]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the app\u2019s <code>urls.py<\/code> file, add the following code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> django.urls <span class=\"hljs-keyword\">import<\/span> path\n\nurlpatterns = &#91;\n\n]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<h4 class=\"wp-block-heading\"><strong>Creating models<\/strong><\/h4>\n\n\n\n<p>With the project setup and routes pattern in place, let\u2019s create a new model to add products to the database in the <code>models.py<\/code> file.&nbsp;<\/p>\n\n\n\n<p>In <code>models.py<\/code>, add the following:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-4\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> django.db <span class=\"hljs-keyword\">import<\/span> models\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Product<\/span><span class=\"hljs-params\">(models.Model)<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0name = models.CharField(max_length=<span class=\"hljs-number\">250<\/span>)\n\n\u00a0\u00a0\u00a0\u00a0price = models.CharField(max_length=<span class=\"hljs-number\">250<\/span>)\n\n\u00a0\u00a0\u00a0\u00a0color = models.CharField(max_length=<span class=\"hljs-number\">250<\/span>)\n\n\u00a0\u00a0\u00a0\u00a0weight = models.CharField(max_length=<span class=\"hljs-number\">250<\/span>)<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-4\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the code block above, we created a new class named <code>Product<\/code> by inheriting <a href=\"https:\/\/docs.djangoproject.com\/en\/4.1\/topics\/db\/models\/\" target=\"_blank\" rel=\"noopener\">Django\u2019s model class<\/a> which lets us define the fields and behaviors of the data we are storing. We then created the class attributes named <code>name<\/code>, <code>price<\/code>, <code>color<\/code>, and <code>weight<\/code> which map as database columns in our table.<\/p>\n\n\n\n<p>Now, let\u2019s migrate our fields to the database. In the command line, we\u2019ll write the following commands to migrate our table to the database.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-5\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\">$ python manage.py makemigrations\n\nMigrations <span class=\"hljs-keyword\">for<\/span> <span class=\"hljs-string\">'productApp'<\/span>:\n\n\u00a0\u00a0productApp\/migrations\/<span class=\"hljs-number\">0001<\/span>_initial.py\n\n\u00a0\u00a0\u00a0\u00a0- Create model Product\n\n$ python manage.py migrate\n\nOperations to perform:\n\n\u00a0\u00a0Apply all migrations: admin, auth, authtoken, contenttypes, polls, productApp, sessions\n\nRunning migrations:\n\n\u00a0\u00a0Applying authtoken<span class=\"hljs-number\">.0001<\/span>_initial... OK\n\n\u00a0\u00a0Applying authtoken<span class=\"hljs-number\">.0002<\/span>_auto_20160226_1747... OK\n\n\u00a0\u00a0Applying authtoken<span class=\"hljs-number\">.0003<\/span>_tokenproxy... OK\n\n\u00a0\u00a0Applying productApp<span class=\"hljs-number\">.0001<\/span>_initial... OK<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-5\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the next section, we will be creating a serializer for our model data.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Creating serializers<\/strong><\/h4>\n\n\n\n<p>Let\u2019s create a new file <code>serializers.py<\/code> in the <code>productApp<\/code> directory and add the following code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-6\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> rest_framework <span class=\"hljs-keyword\">import<\/span> serializers\n\n<span class=\"hljs-keyword\">from<\/span> .models <span class=\"hljs-keyword\">import<\/span> Product\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ProductSerializer<\/span><span class=\"hljs-params\">(serializers.ModelSerializer)<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">Meta<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0model = Product\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0fields = &#91;<span class=\"hljs-string\">\"id\"<\/span>, <span class=\"hljs-string\">\"name\"<\/span>, <span class=\"hljs-string\">\"price\"<\/span>, <span class=\"hljs-string\">\"color\"<\/span>, <span class=\"hljs-string\">\"weight\"<\/span>]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-6\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the code block above,&nbsp; we created a new class for our model serializer. We then added a <a href=\"https:\/\/www.datacamp.com\/tutorial\/python-metaclasses\" target=\"_blank\" rel=\"noopener\">Meta class,<\/a> which lets us define the model we are creating a serializer for and specify the fields of the models we want to output. Serialization in the Django Rest Framework helps us convert model objects into more flexible data types like JSON, which are more understandable by JavaScript and <a href=\"https:\/\/coderpad.io\/demo\/frameworks-and-multi-file-environments\/\">frontend frameworks<\/a>.<\/p>\n\n\n\n<p>Now let\u2019s head over to creating views and routes for our API.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\"><strong>Creating views and routes<\/strong><\/h4>\n\n\n\n<p>In the previous sections, we created a model and serializer to format the output of our data properly. In this section, we will be creating a view for defining our API and a route.<\/p>\n\n\n\n<p>In the <code>views.py<\/code> file in the app\u2019s directory, add the following code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-7\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> rest_framework.generics <span class=\"hljs-keyword\">import<\/span> CreateAPIView, ListAPIView, DestroyAPIView\n\n<span class=\"hljs-keyword\">from<\/span> .models <span class=\"hljs-keyword\">import<\/span> Product\n\n<span class=\"hljs-keyword\">from<\/span> .serializers <span class=\"hljs-keyword\">import<\/span> ProductSerializer\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CreateProduct<\/span><span class=\"hljs-params\">(CreateAPIView)<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0serializer_class = ProductSerializer\n\n\u00a0\u00a0\u00a0\u00a0queryset = Product.objects.all()\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">GetProducts<\/span><span class=\"hljs-params\">(ListAPIView)<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0serializer_class = ProductSerializer\n\n\u00a0\u00a0\u00a0\u00a0queryset = Product.objects.all()\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">DeleteProduct<\/span><span class=\"hljs-params\">(DestroyAPIView)<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0serializer_class = ProductSerializer\n\n\u00a0\u00a0\u00a0\u00a0queryset = Product.objects.all()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-7\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the code block above, we created views to create, get, and delete products using <a href=\"https:\/\/www.django-rest-framework.org\/api-guide\/generic-views\/#concrete-view-classes\" target=\"_blank\" rel=\"noopener\">generic views <\/a>in DRF. This lets us create basic CRUD (create, read, update, and delete) APIs to get and modify data in our database.<\/p>\n\n\n\n<p>We then create the routes for our APIs in the app\u2019s <code>urls.py<\/code> file.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-8\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> django.urls <span class=\"hljs-keyword\">import<\/span> path\n\n<span class=\"hljs-keyword\">from<\/span> .views <span class=\"hljs-keyword\">import<\/span> CreateProduct, GetProducts, DeleteProduct\n\nurlpatterns = &#91;\n\n\u00a0\u00a0\u00a0\u00a0path(<span class=\"hljs-string\">\"create\"<\/span>, CreateProduct.as_view()),\n\n\u00a0\u00a0\u00a0\u00a0path(<span class=\"hljs-string\">\"get\"<\/span>, GetProducts.as_view()),\n\n\u00a0\u00a0\u00a0\u00a0path(<span class=\"hljs-string\">\"delete\"<\/span>, DeleteProduct.as_view()),\n\n]<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-8\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the code block above, we defined routes for our API views created earlier, which let us map to proper resources when requested on our browser.<\/p>\n\n\n\n<p>Now let\u2019s define some throttling policies for our API globally.&nbsp;<\/p>\n\n\n\n<blockquote class=\"wp-block-quote\">\n<p>\ud83d\udca1 The Django REST framework (DRF) provides several classes for implementing throttling in a Django application. These classes are located in the <code>rest_framework.throttling<\/code> module.<\/p>\n<\/blockquote>\n\n\n\n<p>In the <code>settings.py<\/code> file, we will be adding some throttling classes that will tell Django to throttle our APIs according to the policies we set.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-9\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\">REST_FRAMEWORK = {\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'DEFAULT_THROTTLE_CLASSES'<\/span>: &#91;\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'rest_framework.throttling.AnonRateThrottle'<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'rest_framework.throttling.UserRateThrottle'<\/span>\n\n\u00a0\u00a0\u00a0\u00a0],\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'DEFAULT_THROTTLE_RATES'<\/span>: {\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'anon'<\/span>: <span class=\"hljs-string\">'2\/min'<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'user'<\/span>: <span class=\"hljs-string\">'4\/min'<\/span>\n\n\u00a0\u00a0\u00a0\u00a0}\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-9\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the code block above, we defined some throttling classes named <code>UserRateThrottle<\/code> and <code>AnonRateThrottle<\/code>. The <code>UserRateThrottle<\/code> throttles the requests of authenticated users in the app by using the user ID to generate a unique key to throttle against, while the <code>AnonRateThrottle<\/code> throttles the requests of unconfirmed or unauthenticated users in the app by using the IP address to generate a unique key to throttle against.<\/p>\n\n\n\n<p>The <code>DEFAULT_THROTTLE_RATES<\/code> sets the number of requests per period for each type of user. The period can be <code>minute<\/code>, <code>second<\/code>,&nbsp; <code>hour<\/code>, or <code>day<\/code>.<\/p>\n\n\n\n<p>To test this, let\u2019s try the create product endpoint and attempt to create a new product more than twice in the same minute. In the sandbox shell, execute the request:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-10\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\">curl --location --request POST <span class=\"hljs-string\">'http:\/\/0.0.0.0:3000\/products\/create'<\/span> \\\n\n--header <span class=\"hljs-string\">'Content-Type: application\/json'<\/span> \\\n\n--data-raw <span class=\"hljs-string\">'{\n\n\u00a0\u00a0\u00a0\u00a0\"name\": \"Foodco\",\n\n\u00a0\u00a0\u00a0\u00a0\"price\": \"3000\",\n\n\u00a0\u00a0\u00a0\u00a0\"color\": \"blue\",\n\n\u00a0\u00a0\u00a0\u00a0\"weight\": \"32kg\"\n\n}'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-10\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the code block above, we made a request to create a product.<\/p>\n\n\n\n<p>When we try the create product endpoint for the third time in the same minute, we will get a <code>429<\/code> too many requests error code and the response shown below.&nbsp;<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-11\" data-shcb-language-name=\"JSON \/ JSON with Comments\" data-shcb-language-slug=\"json\"><span><code class=\"hljs language-json shcb-wrap-lines\">\u200b\u200b{<span class=\"hljs-attr\">\"detail\"<\/span>:<span class=\"hljs-string\">\"Request was throttled. Expected available in 58 seconds.\"<\/span>}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-11\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JSON \/ JSON with Comments<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">json<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>The throttle classes can also be defined on each view. For example, we can rewrite the <code>CreateProduct<\/code> view and specify the throttle class.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-12\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> rest_framework.throttling <span class=\"hljs-keyword\">import<\/span> UserRateThrottle\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CreateProduct<\/span><span class=\"hljs-params\">(CreateAPIView)<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0throttle_classes = &#91;UserRateThrottle]\n\n\u00a0\u00a0\u00a0\u00a0serializer_class = ProductSerializer\n\n\u00a0\u00a0\u00a0\u00a0queryset = Product.objects.all()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-12\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the code above, we defined the throttle class on the <code>CreateProduct<\/code> view by adding it as an attribute.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Multiple user rate throttle<\/h3>\n\n\n\n<p>We may want to set different throttling policies for an API. To accomplish this, we define multiple user rate throttles for users by overriding the default throttle class and adding a scope value that will be used to identify them when defining the throttle rate.<\/p>\n\n\n\n<p>Let\u2019s create a new file in the app\u2019s directory named <code>throttles.py<\/code>.<\/p>\n\n\n\n<p>In <code>throttles.py<\/code>,&nbsp; let\u2019s add the following code:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-13\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> rest_framework.throttling <span class=\"hljs-keyword\">import<\/span> UserRateThrottle\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">HighRateThrottle<\/span><span class=\"hljs-params\">(UserRateThrottle)<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0scope = <span class=\"hljs-string\">'high'<\/span>\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">LowRateThrottle<\/span><span class=\"hljs-params\">(UserRateThrottle)<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0scope = <span class=\"hljs-string\">'low'<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-13\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We will change the <code>settings.py<\/code> file to the new throttle classes defined:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-14\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\">REST_FRAMEWORK = {\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'DEFAULT_THROTTLE_CLASSES'<\/span>: &#91;\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'productApp.throttles.HighRateThrottle'<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'productApp.throttles.LowRateThrottle'<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0],\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'DEFAULT_THROTTLE_RATES'<\/span>: {\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'high'<\/span>: <span class=\"hljs-string\">'30\/minute'<\/span>,\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'low'<\/span>: <span class=\"hljs-string\">'4\/minute'<\/span>\n\n\u00a0\u00a0\u00a0\u00a0}\n\n}<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-14\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>In the code block above, we override the <code>UserRateThrottle<\/code> class and define two new throttles to handle requests based on the policies set. The high-rate throttle will handle more requests in a minute than the low-rate throttle.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Scoped rate throttle<\/h3>\n\n\n\n<p>We may want to limit access to some APIs while increasing access to others. This is accomplished by setting the default throttle class to <code>ScopedRateThrottle<\/code> and including a &#8216;throttle scope&#8217; property in our view.<\/p>\n\n\n\n<p>For example, let\u2019s override our throttle settings in the <code>settings.py<\/code> file.<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-15\" data-shcb-language-name=\"PHP\" data-shcb-language-slug=\"php\"><span><code class=\"hljs language-php shcb-wrap-lines\">REST_FRAMEWORK = {\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'DEFAULT_THROTTLE_CLASSES'<\/span>: &#91;\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">\"rest_framework.throttling.ScopedRateThrottle\"<\/span>\n\n\u00a0\u00a0\u00a0\u00a0],\n\n\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'DEFAULT_THROTTLE_RATES'<\/span>: {\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0<span class=\"hljs-string\">'high'<\/span>: <span class=\"hljs-string\">'30\/day\u2019,\n\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0'<\/span>low<span class=\"hljs-string\">': '<\/span><span class=\"hljs-number\">4<\/span>\/day<span class=\"hljs-string\">'\n\n\u00a0\u00a0\u00a0\u00a0}\n\n}<\/span><\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-15\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">PHP<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">php<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>Then, in our view, we define the throttle scope for each view:<\/p>\n\n\n<pre class=\"wp-block-code\" aria-describedby=\"shcb-language-16\" data-shcb-language-name=\"Python\" data-shcb-language-slug=\"python\"><span><code class=\"hljs language-python shcb-wrap-lines\"><span class=\"hljs-keyword\">from<\/span> rest_framework.generics <span class=\"hljs-keyword\">import<\/span> CreateAPIView, ListAPIView, DestroyAPIView\n\n<span class=\"hljs-keyword\">from<\/span> .models <span class=\"hljs-keyword\">import<\/span> Product\n\n<span class=\"hljs-keyword\">from<\/span> .serializers <span class=\"hljs-keyword\">import<\/span> ProductSerializer\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">CreateProduct<\/span><span class=\"hljs-params\">(CreateAPIView)<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0throttle_scope = <span class=\"hljs-string\">\"low\"<\/span>\n\n\u00a0\u00a0\u00a0\u00a0serializer_class = ProductSerializer\n\n\u00a0\u00a0\u00a0\u00a0queryset = Product.objects.all()\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">GetProducts<\/span><span class=\"hljs-params\">(ListAPIView)<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0throttle_scope = <span class=\"hljs-string\">\"high\"<\/span>\n\n\u00a0\u00a0\u00a0\u00a0serializer_class = ProductSerializer\n\n\u00a0\u00a0\u00a0\u00a0queryset = Product.objects.all()\n\n<span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">DeleteProduct<\/span><span class=\"hljs-params\">(DestroyAPIView)<\/span>:<\/span>\n\n\u00a0\u00a0\u00a0\u00a0throttle_scope = <span class=\"hljs-string\">\"low\"<\/span>\n\n\u00a0\u00a0\u00a0\u00a0serializer_class = ProductSerializer\n\n\u00a0\u00a0\u00a0\u00a0queryset = Product.objects.all()<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-16\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">Python<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">python<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n\n\n<p>We defined a <code>throttle_scope<\/code> in the code block above for each view. The user requests on the endpoint to <code>create<\/code> and <code>delete<\/code> products will be restricted to 4 per day, while the user requests to <code>get<\/code> products will be as high as 30 per day.<\/p>\n\n\n\n<p>Test the request rate limiter built in this article in the sandbox below:<\/p>\n\n\n<div\n\tclass=\"sandbox-embed responsive-embed  sandbox-embed--full-width\"\n\tstyle=\"padding-top: 85%\"\ndata-block-name=\"coderpad-sandbox-embed\">\n\t<iframe src=\"https:\/\/embed.coderpad.io\/sandbox?question_id=237433&#038;use_question_button\" width=\"640\" height=\"544\" loading=\"lazy\" aria-label=\"Try out the CoderPad sandbox\"><\/iframe>\n<\/div>\n\n\n\n<h2 class=\"wp-block-heading\">Conclusion<\/h2>\n\n\n\n<p>In this article, we have discussed rate limiting and why it is essential. We also discussed the different types of rate limiting, which include user rate limiting, geographic-based rate limiting, and server rate limiting. We then discussed how to implement rate limiting using various methods, including throttling, request queues, and different rate-limiting algorithms. In the last part of the article, we created an API in the Django Rest Framework and explained how to set throttling on the APIs using different throttling classes, giving us a better understanding of how rate limiting works and how we can use it in Django Rest Framework APIs.<\/p>\n\n\n\n<p><em>Ubaydah is a backend developer experienced in building APIs and writing documentation. She loves sharing technical knowledge in form of articles to educate others.<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>API rate limiting is one of the most effective practices for improving security and preventing large spikes in API request calls, which can degrade overall performance. Learn how to efficiently manage requests to your API server in this article.<\/p>\n","protected":false},"author":1,"featured_media":28062,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[9],"tags":[],"persona":[29],"blog-programming-language":[37],"keyword-cluster":[],"class_list":["post-27347","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-development"],"acf":[],"_links":{"self":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/27347","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/comments?post=27347"}],"version-history":[{"count":95,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/27347\/revisions"}],"predecessor-version":[{"id":34560,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/posts\/27347\/revisions\/34560"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media\/28062"}],"wp:attachment":[{"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/media?parent=27347"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/categories?post=27347"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/tags?post=27347"},{"taxonomy":"persona","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/persona?post=27347"},{"taxonomy":"blog-programming-language","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/blog-programming-language?post=27347"},{"taxonomy":"keyword-cluster","embeddable":true,"href":"https:\/\/coderpad.io\/wp-json\/wp\/v2\/keyword-cluster?post=27347"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}