How to Rate Limit Routes in Flask
Flask is a web framework written in python. It provides you with tools, libraries, and technologies that allow you to build a web applications. These web application can be some web pages, a blog, a wiki or go as big as a web-based calendar application or a commercial website.
What is Rate Limiting?
Rate Limiting allows you to control how often someone can access your API in a given time period. In flask there is a extension called flask limiter. This extension allows you to limit the amount of request on a particular route. Each route can have different request limits or be exempt to have no limits. It limits user by keeping track of their IP address.
Why you should use it?
An API endpoint shouldn’t be unlimited access. We need to make sure our application routes are running efficiently as possible. Focusing on performance of our application is important because we don’t want users to have a bad experience. It also helps keep costs down with limit requests and increases our security from DoS attacks.
How to implement it?
We are using the flask_limiter
library to provide rate limiting features in our flask app. Following the documentation you will need some imports. Make sure your environment has flask
and flask-limiter
installed.
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
After those imports, you will need to add a default limiter. Use this code snippet below.
limiter = Limiter(
application,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)
For the Limiter
first arg should be the name of main flask file application. Then key_func
should equal get_remote_address
. You can set the default_limits
to anything you want.
Under each route you can individually customize the request limits and it will bypass the default limits.
# example 5 per minute route
@application.route("/slow")
@limiter.limit("5 per minute")
def slow():
return "5 per minute!"
We can also exempt a route from the default limit and users will have unlimited access to that route.
# example no limit route
@application.route("/exempt")
@limiter.exempt
def exempt():
return "No limits!"
Example Flask App:
Copy and paste code block below into application.py file and run
from flask import Flask
from flask_limiter import Limiter
from flask_limiter.util import get_remote_addressapplication = Flask(__name__)limiter = Limiter(
application,
key_func=get_remote_address,
default_limits=["200 per day", "50 per hour"]
)@application.route("/")
def default():
return "default limit!"@application.route("/five")
@limiter.limit("5 per minute")
def five():
return "5 per minute!"
@application.route("/exempt")
@limiter.exempt
def exempt():
return "No limits!"
if __name__ == "__main__":
application.run(port=5000, debug=True)
Test each route and set the limits to anything you want. It’s also possible to have multiple limits for one route. Every time a request exceeds the rate limit, the function will not get called and instead a 429 http error will be raised.
Rate Limit String Notation
Example:
- 10 per minute
- 10 per hour
- 10/hour
- 10/hour;100/day;2000 per year
- 100/day, 500/7days
- 100/day, 500/7days
The limit request will be determine by the application you will run. So you will know the best rate for each route. :)
This article will eventually become part of a series of articles from lessons I learned with my team while working on a project called Cryptolytic (article will be written about this soon and linked here). It’s the guide we wish we had when working on the project.
This article will eventually become part of a series of articles from lessons I learned with my team while working on a project called Cryptolytic (article will be written about this soon and linked here). It’s the guide we wish we had when working on the project.
The notebook containing all the code used in this article can be found here which is inside the repo of our Cryptolytic project — so if you’re curious, check it out!
Find me on Twitter @malexmad, Github, or connect with me on LinkedIn!