Rate Limiting with Kong API Gateway
In this article, we will learn how to use Kong to manage API endpoints. The article is organized as follows:
- builds a simple "Hello World" API using Python, FastAPI, and Uvicorn
- uses Kong API gateway to rate limit clients' requests to the server
"Hello World!" API
Create a FastAPI application
To create a simple FastAPI application in Python, begin by installing the FastAPI Python package:
pip install fastapiYou can consider using a virtual environment to isolate dependencies. Now, create a file named "main.py" for our API and add the following code:
from fastapi import FastAPI
app = FastAPI()
@app.get("/hello_world")
async def hello_world():
return {"message": "Hello World!"}
This defines an API endpoint /hello_world that returns a "Hello World!" message.
API server with Uvicorn
To set up a local server for your API, install Uvicorn package for Python:
pip install uvicornTo start the server using Uvicorn, run
uvicorn main:app --host 127.0.0.1 --port 5000This will make the API available at http://localhost:5000/hello_world. To test the API, use the command:
curl http://localhost:5000/hello_world'If the API has been set up correctly, you will receive the following JSON response:
{"message": "Hello World!}}Kong API gateway and rate limiting
In this section, we will configure Kong API gateway for rate limiting user's request to the FastAPI server.
Installing Kong as a Docker container
To install Kong on your system, you can use the docker compose file provided below.
services:
postgres_kong:
image: postgres:18.2
container_name: postgres_kong
restart: unless-stopped
environment:
POSTGRES_USER: demo_user
POSTGRES_PASSWORD: strong_password
POSTGRES_DB: kong
volumes:
- ./data/postgres:/var/lib/postgresql
healthcheck:
test: ["CMD-SHELL", "pg_isready -U demo_user -d kong"] # Specify database name or else it will reuse username as database name
interval: 5s
timeout: 5s
retries: 5
networks:
- kong_api_gateway
kong:
image: kong:3
container_name: kong
restart: unless-stopped
depends_on:
postgres_kong:
condition: service_healthy
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: postgres_kong
KONG_PG_USER: demo_user
KONG_ADMIN_LISTEN: 0.0.0.0:8001 # Without this Kong does not listen outside container
KONG_PG_PASSWORD: strong_password
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
ports:
- "8000:8000" # Public proxy
- "8001:8001" # Admin API (secure this in production)
command: >
sh -c "kong migrations bootstrap && kong start"
networks:
- kong_api_gateway
networks:
kong_api_gateway:
driver: bridge
name: kong_api_gateway
To use this compose file, open a terminal in the working directory and execute the command:
docker compose up -d
Docker will automatically fetch all images from docker hub and start Kong as a docker container.
Interacting with Kong API gateway
By default, Kong listens on two ports: 8000 and 8001. Port 8000 is for clients to access API end points whereas port 8001 connects to Kong Admin API for managing the gateway. It is, therefore, important that you do not expose port 8001 publicly in the production environment.
Unrestricted access on FastAPI server
The hello world API, discussed in , is accessible on port 5000. Before proceeding with the configuration of Kong as the API gateway, it is recommended to implement this API as a Docker container. To try out this tutorial, you can download the docker compose file along with the hello_world python code.
To understand why we need Kong, send consecutive requests on hello_world API to observe that there is no inherent rate limit. As unrestricted access can possibly overload the server, we will learn how to use Kong as a API gateway to limit the rate of requests. We will do this in three parts. First, we will set up a service to store information about the hello world api. Next, we will declare a route to relay API request to this service. Finally, we will use a Kong plugin for rate limiting. Once the gateway is configured, you should also restrict public access to port 5000 so that only Kong gateway can be used to access the hello world API.
Kong Admin API
Kong Admin API on port 8001 allows us to manage the Kong API gateway.
Set up a service in Kong
Let's start by sending a GET request to the Kong Admin API on port 8001 to list all available services.
curl http://localhost:8001/services
At this point, no services are registered with Kong, so, the response will be an empty object. To set up the first service, send a POST request to the Kong Admin API to add a new service. The POST request shouuld also specify the desired name and the url of the service.
curl -X POST http://localhost:8001/services \
--data "name=hello_world" \
--data "url=http://fastapi:5000/hello_world"
I have set up the hello world API as another docker container. This allows me to use the docker service name in the url instead of IP address. Using the docker service name eliminates the problem of dynamic IP addresses. Also, it eliminates the need to expose port 5000 outside the docker network.
Once the service is registered, you can verify by sending another GET request to Kong Admin API and list all services.
curl http://localhost:8001/services
On a side note, if you want the returned json string to be easier to read, you can append | jq to the curl request. The jq tools formats the JSON output with proper indentation.
Set up a route in Kong
Now, send a POST request to Kong Admin API to set up a new route for the hello world service and specify the name and a desired path for this route as a part of the requst.
curl -X POST http://localhost:8001/services/hello_world/routes \
--data "name=hello_world_through_gateway"
--data "paths[]=/hello_world_through_gateway"
In case you want to verify that the route has been registered, you can send a GET request to the Kong Admin API to list down all routes
curl https://locahost:8001/routes
Let's go ahead and test the route. As mentioned earlier, Kong listens on port 8000 for API requests. So, send a GET request using the command:
curl http://localhost:8000/hello_world_through_gateway
The API should return the hello world message.
Set up the rate limit plugin in Kong
The basic configuration for Kong gateway is done. Now, we will set up a plugin to limit the API access rate. To achieve this, make a POST request to the Kong admin API and add a plugin to the hello_world service. For this, you need to specify the name of the plugin and configure the rate limit as a part of the request
curl -X POST http://localhost:8001/services/hello_world/plugins \
--data "name=rate-limiting" \
--data "config.minute=5"
For demonstration, I have configured the rate limit to 5 requests per minute. To verify that the plugin was successfully implemented, you can generate the list of all plugins associated with the hello_world service using the command:
curl http://localhost:8001/services/hello_world/plugins
To test the plugin, send consecutive requests to Kong gateway. You will notice that after 5 successful requests, Kong responds with a message that the rate limit for the service has been exceeded. While testing the rate limiting plugin, sometimes you will be able to make more than 5 successful requests. This is because the plugin uses a fixed time window to count the number of requests. So, if your multiple requests get split over two consecutive time windows, you will be able to make up to 10 successful API requests.
Author
Anurag Gupta is an M.S. graduate in Electrical and Computer Engineering from Cornell University. He also holds an M.Tech degree in Systems and Control Engineering and a B.Tech degree in Electrical Engineering from the Indian Institute of Technology, Bombay.
Comment
This policy contains information about your privacy. By posting, you are declaring that you understand this policy:
- Your name, rating, website address, town, country, state and comment will be publicly displayed if entered.
- Aside from the data entered into these form fields, other stored data about your comment will include:
- Your IP address (not displayed)
- The time/date of your submission (displayed)
- Your email address will not be shared. It is collected for only two reasons:
- Administrative purposes, should a need to contact you arise.
- To inform you of new comments, should you subscribe to receive notifications.
- A cookie may be set on your computer. This is used to remember your inputs. It will expire by itself.
This policy is subject to change at any time and without notice.
These terms and conditions contain rules about posting comments. By submitting a comment, you are declaring that you agree with these rules:
- Although the administrator will attempt to moderate comments, it is impossible for every comment to have been moderated at any given time.
- You acknowledge that all comments express the views and opinions of the original author and not those of the administrator.
- You agree not to post any material which is knowingly false, obscene, hateful, threatening, harassing or invasive of a person's privacy.
- The administrator has the right to edit, move or remove any comment for any reason and without notice.
Failure to comply with these rules may result in being banned from submitting further comments.
These terms and conditions are subject to change at any time and without notice.
Similar content
Past Comments