Skip to main content

Rate limit Datasette requests by client IP address

Project description

datasette-ip-rate-limit

PyPI Changelog Tests License

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 to 10000.
  • exempt_paths: Path patterns that should never be rate limited.
  • rules: List of rate limit rules. The first matching rule is used.
  • debug: Set to true to 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 to 60.
  • max_requests: Number of requests allowed per window. Defaults to 60.
  • block_seconds: How long to block an IP after it exceeds the rate. Defaults to 300.

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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

datasette_ip_rate_limit-0.1a0.tar.gz (11.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

datasette_ip_rate_limit-0.1a0-py3-none-any.whl (10.1 kB view details)

Uploaded Python 3

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

Hashes for datasette_ip_rate_limit-0.1a0.tar.gz
Algorithm Hash digest
SHA256 146fa15e6e8ada4a3c009d01d9e95de6717158356abce5954503227b827668f2
MD5 5b058ef3e81c6276a2f7dec07d396554
BLAKE2b-256 09296047f5f3f940711bfd3f1c08e2beae71857204798c4748c96eec736e0e6a

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file datasette_ip_rate_limit-0.1a0-py3-none-any.whl.

File metadata

File hashes

Hashes for datasette_ip_rate_limit-0.1a0-py3-none-any.whl
Algorithm Hash digest
SHA256 220efc3beb2cb8290daf7f057c91943d0d487a30d58c193a749b0e971b10c3d8
MD5 187b1dab8dae1febb03ab9c76a72f0a5
BLAKE2b-256 f6efae73f5018e5a418f49f319c5dba8e69cd4840fd77152fe4876f5f8312147

See more details on using hashes here.

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

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page