Master Middleware through Practical Application: Implementing Rate Limiting with FastAPI

Posted by


In this tutorial, we will learn how to build a real project using FastAPI and implement rate limiting using middleware. Rate limiting is a technique used to control the rate at which clients can make requests to a server or API. This can help prevent abuse, protect the server from being overwhelmed, and ensure fair usage for all clients.

FastAPI is a modern web framework for building APIs with Python. It is fast, easy to use, and comes with built-in support for various features like dependencies, validation, and middleware.

In this tutorial, we will be building a simple API that serves a list of items. We will implement rate limiting using middleware to restrict the number of requests a client can make within a certain time window.

To get started, make sure you have Python installed on your machine. You can install FastAPI using pip:

pip install fastapi

Next, we will create a new Python file for our project. Let’s call it main.py. In this file, we will define our FastAPI application and create the necessary endpoints.

from fastapi import FastAPI

app = FastAPI()

@app.get("/items")
def get_items():
    return {"items": ["item1", "item2", "item3"]}

if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=8000)

In this code, we have defined a single endpoint /items that returns a list of items. Now let’s implement rate limiting for this endpoint using middleware.

Middleware in FastAPI is a function that intercepts and processes requests before they reach the endpoint handler. We can define a middleware function that checks if the client has exceeded the request rate limit and returns a 429 status code if they have.

First, we need to install an additional package called ratelimit:

pip install ratelimit

Now, let’s create a new file called middleware.py and define our rate limiting middleware:

from fastapi import Request
from fastapi.responses import PlainTextResponse
from ratelimit import limits, RateLimitException
from datetime import datetime

@limits(calls=5, period=60)
def rate_limit_by_ip(request: Request):
    pass

async def rate_limit_middleware(request: Request, call_next):
    try:
        rate_limit_by_ip(request)
    except RateLimitException as e:
        return PlainTextResponse(str(e), status_code=429)

    response = await call_next(request)
    return response

In this code, we have defined a rate limit of 5 requests per minute for each client IP address. If a client exceeds this limit, a RateLimitException will be raised, and a 429 status code will be returned.

Next, we need to add our middleware to the FastAPI application. In main.py, import the middleware functions and add them to the application using the add_middleware method:

from fastapi import FastAPI
from middleware import rate_limit_middleware

app = FastAPI()

@app.get("/items")
def get_items():
    return {"items": ["item1", "item2", "item3"]}

if __name__ == "__main__":
    import uvicorn
    app.add_middleware(rate_limit_middleware)
    uvicorn.run(app, host="0.0.0.0", port=8000)

Now, when a client makes more than 5 requests to the /items endpoint within a 1-minute window, they will receive a 429 status code indicating they have exceeded the rate limit.

That’s it! You have successfully implemented rate limiting using middleware in a FastAPI project. You can further customize the rate limit settings, such as the number of calls and the time period, to suit your needs.

I hope this tutorial was helpful in learning how to build a real project with FastAPI and implement rate limiting. Happy coding!

0 0 votes
Article Rating
9 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
@LiftAndC0de
1 month ago

Hi Eric, I'm doing a project with Rate Limiting using the pure ASGI middleware from Starlette to get better performance, but this is on dev mode, my question is about how to get this ready to production, a production environment this couldn't be the best, so I guess I'll need to use Redis, right? Thank you for your videos, they're awesome!

@noahadad37
1 month ago

Hi. Great video!
I have a question,
in case that we are calling to sync func that doesn't have await (in await call_next(req)) – the app is not processing other requests until this request finishes?

@moverecursus1337
1 month ago

Great Video! Awesome Channel! Thanks!

@Mrprogramer-li4ok
1 month ago

if you create a complete application using sqlmodel, that would be outstanding.

@djtoon8412
1 month ago

can we get a microservices tutorial using gRPC, i guess it some missing piece of information on youtube.

@Website-Content-Creator
1 month ago

hellow sir could you please guide how to make quiz app using fastapi

@mrkzmusic
1 month ago

I didn't know what a middleware was and now I have a new to do task in my project

@craig_drummond
1 month ago

Great video! I can use this in a project at work today!

@praveenRI-qi3sn
1 month ago

Hey Ruby ! great video btw . i have a question , while implementing this i have several js css files which are making individual calls for loading the page , so rate limiter is failing here . how to load all js , css files in one bundle request : for reference comment image