Prevent API overload with rate limiting in AWS
--
In the early days of the covid pandemic, and for a significant period, when we went to the supermarket, we had to wait in a queue for our turn to enter the supermarket. Only a certain number of customers could shop together at a particular time. The intention was to keep a physical distance between individuals to limit the spread of the virus, hence keeping people safe and limiting the load on the health system.
That’s similar to what we do in Software when we rate limit our APIs. We do it for multiple reasons, including preventing abuse (e.g. malicious user overwhelming the system with too many requests), managing downstream services and resources (e.g. database) or simply using rate limit as a way to monetize the APIs (e.g. enabling free users to use the APIs less frequently than paid users).
This post will build an API using AWS API Gateway and explore how to rate-limit calls to our endpoints. API Gateway is a managed service from AWS that helps you publish, manage and monitor your APIs. We will use Terraform to set up our infrastructure.
We deploy APIs to stages in API Gateway, where each stage has a single deployment. You could have one stage for development, one for testing and one for production. Each stage has its URL and settings.
We will build an endpoint that returns the number of people in the supermarket. It will be of this shape: GET /…/prod/customers
.
Build the API
In Terraform:
- Create the REST API
resource "aws_api_gateway_rest_api" "api" {
name = "SupermarketCustomers"
description = "Tracks the number of customers that enter the supermarket"
endpoint_configuration {
types = ["REGIONAL"]
}
}
- Create the “Customers” resource. That will be the first endpoint:
resource "aws_api_gateway_resource" "customers_resource" {
rest_api_id = aws_api_gateway_rest_api.api.id
parent_id = aws_api_gateway_rest_api.api.root_resource_id
path_part = "customers"
}
- Create the method for this resource — GET in this case:
resource "aws_api_gateway_method" "get_method" {
rest_api_id = aws_api_gateway_rest_api.api.id
resource_id =…