Rate limit Datasette requests by client IP address
Project description
datasette-ip-rate-limit
Rate limit Datasette requests by client IP address.
This plugin is designed for Datasette instances that need a lightweight in-process guard against one client sending too many expensive requests.
Installation
Install this plugin in the same environment as Datasette.
datasette install datasette-ip-rate-limit
Configuration
Configure the plugin in datasette.yaml:
plugins:
datasette-ip-rate-limit:
debug: true
rules:
- paths:
- "/*"
block_seconds: 20
This applies rate limiting to every non-debug path and enables
/-/ip-rate-limit-debug so you can inspect the current in-memory state.
For a more targeted configuration:
plugins:
datasette-ip-rate-limit:
max_keys: 10000
exempt_paths:
- "/static/*"
- "/-/turnstile*"
rules:
- name: expensive-table-pages
paths:
- "/global-power-plants/*"
- "/legislators/*"
query_params_min: 2
window_seconds: 60
max_requests: 120
block_seconds: 600
This allows each IP address to make 120 matching requests per 60 seconds. If
an IP exceeds that rate, it receives 429 Too Many Requests responses for 600
seconds with a Retry-After header.
The example only applies to matching table pages with at least two query string parameters, so ordinary page views are left alone.
By default, the client IP address is read from the ASGI connection. If
Datasette is running behind a trusted proxy, set header to the request header
that proxy uses for the client IP address.
Options
header: Optional request header used for the client IP instead of the ASGI connection address.max_keys: Maximum number of(rule, IP)entries kept in memory. Defaults to10000.exempt_paths: Path patterns that should never be rate limited.rules: List of rate limit rules. The first matching rule is used.debug: Set totrueto enable/-/ip-rate-limit-debug, a debug page showing the current in-memory rate limit state as pretty-printed JSON. This includes client IP addresses, so it should only be enabled while debugging.
Each rule supports:
name: Stable rule name used as part of the in-memory key. Defaults to the rule index.paths: Path patterns to match.*matches any characters.methods: Optional list of HTTP methods to match.query_params_min: Optional minimum number of query string parameters required before the rule applies.window_seconds: Token refill window. Defaults to60.max_requests: Number of requests allowed per window. Defaults to60.block_seconds: How long to block an IP after it exceeds the rate. Defaults to300.
Memory Behavior
The limiter uses a token bucket, not a sliding request log. It stores one small record for each tracked (rule, IP) pair: token count, last update time, and optional blocked-until time.
The max_keys setting caps the number of tracked records. If more keys are seen, the least recently used keys are evicted. That bounds RAM usage even if a crawler rotates through many IP addresses.
This is intentionally fail-open for evicted keys: if a key is evicted and later appears again, it starts with a fresh bucket.
Development
To run the tests:
uv run pytest
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file datasette_ip_rate_limit-0.1a0.tar.gz.
File metadata
- Download URL: datasette_ip_rate_limit-0.1a0.tar.gz
- Upload date:
- Size: 11.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
146fa15e6e8ada4a3c009d01d9e95de6717158356abce5954503227b827668f2
|
|
| MD5 |
5b058ef3e81c6276a2f7dec07d396554
|
|
| BLAKE2b-256 |
09296047f5f3f940711bfd3f1c08e2beae71857204798c4748c96eec736e0e6a
|
Provenance
The following attestation bundles were made for datasette_ip_rate_limit-0.1a0.tar.gz:
Publisher:
publish.yml on datasette/datasette-ip-rate-limit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datasette_ip_rate_limit-0.1a0.tar.gz -
Subject digest:
146fa15e6e8ada4a3c009d01d9e95de6717158356abce5954503227b827668f2 - Sigstore transparency entry: 1530507095
- Sigstore integration time:
-
Permalink:
datasette/datasette-ip-rate-limit@8d338b0898d7e7e816f90723e99e219993c307c5 -
Branch / Tag:
refs/tags/0.1a0 - Owner: https://github.com/datasette
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8d338b0898d7e7e816f90723e99e219993c307c5 -
Trigger Event:
release
-
Statement type:
File details
Details for the file datasette_ip_rate_limit-0.1a0-py3-none-any.whl.
File metadata
- Download URL: datasette_ip_rate_limit-0.1a0-py3-none-any.whl
- Upload date:
- Size: 10.1 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
220efc3beb2cb8290daf7f057c91943d0d487a30d58c193a749b0e971b10c3d8
|
|
| MD5 |
187b1dab8dae1febb03ab9c76a72f0a5
|
|
| BLAKE2b-256 |
f6efae73f5018e5a418f49f319c5dba8e69cd4840fd77152fe4876f5f8312147
|
Provenance
The following attestation bundles were made for datasette_ip_rate_limit-0.1a0-py3-none-any.whl:
Publisher:
publish.yml on datasette/datasette-ip-rate-limit
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
datasette_ip_rate_limit-0.1a0-py3-none-any.whl -
Subject digest:
220efc3beb2cb8290daf7f057c91943d0d487a30d58c193a749b0e971b10c3d8 - Sigstore transparency entry: 1530507181
- Sigstore integration time:
-
Permalink:
datasette/datasette-ip-rate-limit@8d338b0898d7e7e816f90723e99e219993c307c5 -
Branch / Tag:
refs/tags/0.1a0 - Owner: https://github.com/datasette
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@8d338b0898d7e7e816f90723e99e219993c307c5 -
Trigger Event:
release
-
Statement type: