Configurable mock API server with realistic rate limiting for testing
Project description
mocklimit
Configurable mock API server with realistic rate limiting for testing. Point it at an OpenAPI spec, define rate limit policies in YAML, and get a local server that behaves like a rate-limited production API, complete with correct headers, 429 responses, and token usage estimation.
Features
- OpenAPI spec auto-routing - parses your spec and registers all endpoints with dummy responses
- Fixed window rate limiting with sub-second precision
- Quantized rate limiter for aligned reset windows
- Composite limits - stack multiple limits per endpoint (e.g. RPM + TPM)
- Provider-accurate headers - configurable header names (
x-ratelimit-limit-requests, etc.) - Token usage estimation for LLM API mocking
- Configurable response latency simulation
- Per-key scoping by API key or IP address
- Request statistics via
/mocklimit/stats - Prometheus metrics at
/metrics-- request counts, latency histograms, rate limit gauges
Installation
pip install mocklimit
Or with uv:
uv add mocklimit
Quick start
1. Create a rate limit config
# limits.yaml
policies:
openai_chat:
strategy: fixed_window
limits:
- max_requests: 5
window_seconds: 60
scope: api_key
response_latency_ms: [0, 0]
headers:
limit: x-ratelimit-limit-requests
remaining: x-ratelimit-remaining-requests
reset: x-ratelimit-reset-requests
endpoints:
/chat/completions:
methods: [POST]
policy: openai_chat
token_estimation:
input: characters_div_4
output: [50, 500]
2. Start the server
mocklimit serve --spec openapi.yaml --rate-config limits.yaml
The server reads your OpenAPI spec for route definitions and response schemas,
then applies rate limiting according to the config. Requests beyond the limit
get a 429 with appropriate Retry-After and rate limit headers.
3. Options
mocklimit serve --spec <path> --rate-config <path> [--host HOST] [--port PORT]
| Flag | Default | Description |
|---|---|---|
--spec |
(required) | Path to OpenAPI spec (YAML) |
--rate-config |
(required) | Path to rate limit config (YAML) |
--host |
127.0.0.1 |
Host to bind to |
--port |
8000 |
Port to listen on |
Rate limit config reference
Policies
Each policy defines a rate limiting strategy:
| Field | Type | Description |
|---|---|---|
strategy |
"fixed_window" |
Rate limiting algorithm |
limits |
list | One or more {max_requests, window_seconds} pairs |
scope |
"api_key" | "ip" |
How to identify clients |
response_latency_ms |
[min, max] |
Simulated response delay range (ms) |
headers.limit |
string | Header name for the request limit |
headers.remaining |
string | Header name for remaining requests |
headers.reset |
string | Header name for reset time |
Endpoints
Map API paths to policies:
| Field | Type | Description |
|---|---|---|
methods |
list of strings | HTTP methods to rate limit |
policy |
string | Name of the policy to apply |
token_estimation |
object (optional) | {input: "characters_div_4", output: [min, max]} |
Prometheus metrics
mocklimit exposes a Prometheus-compatible scrape endpoint at /metrics/.
Exposed metrics
| Metric | Type | Labels | Description |
|---|---|---|---|
mocklimit_requests_total |
Counter | endpoint, method, scope_key, status |
Total requests to rate-limited endpoints |
mocklimit_rate_limited_total |
Counter | endpoint, method, scope_key |
Requests denied with 429 |
mocklimit_request_duration_seconds |
Histogram | endpoint, method, status |
Handler latency including simulated delay |
mocklimit_rate_limit_remaining |
Gauge | endpoint, policy, scope_key |
Remaining requests in the current window |
Prometheus scrape config
scrape_configs:
- job_name: mocklimit
metrics_path: /metrics/
static_configs:
- targets: ["localhost:8000"]
Example output
After a few requests:
mocklimit_requests_total{endpoint="POST /chat/completions",method="POST",scope_key="my-key",status="200"} 5.0
mocklimit_requests_total{endpoint="POST /chat/completions",method="POST",scope_key="my-key",status="429"} 1.0
mocklimit_rate_limited_total{endpoint="POST /chat/completions",method="POST",scope_key="my-key"} 1.0
mocklimit_rate_limit_remaining{endpoint="POST /chat/completions",policy="chat",scope_key="my-key"} 0.0
mocklimit_request_duration_seconds_count{endpoint="POST /chat/completions",method="POST",status="200"} 5.0
Programmatic usage
You can also embed the server directly in tests:
from mocklimit.server import create_app
app = create_app("openapi.yaml", "limits.yaml")
This returns a standard FastAPI app that can be used with any ASGI test client.
License
MIT
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
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 mocklimit-0.3.0.tar.gz.
File metadata
- Download URL: mocklimit-0.3.0.tar.gz
- Upload date:
- Size: 16.3 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
1c2a4e1ace51b00068251acac196837d223f7c6e7f2d7cb61cf76d63ae18a0a1
|
|
| MD5 |
5e4f38d078e149466c1a79bd14d27de7
|
|
| BLAKE2b-256 |
73c2b8c95dbc14f01e93a6c27f8a6af4a42e3d497294992326cf56a6dbaf5bd8
|
File details
Details for the file mocklimit-0.3.0-py3-none-any.whl.
File metadata
- Download URL: mocklimit-0.3.0-py3-none-any.whl
- Upload date:
- Size: 24.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: uv/0.11.6 {"installer":{"name":"uv","version":"0.11.6","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
472768bfddf9272dd1528fe9e0fa09404ed014aba77f8301b52601357f544c7e
|
|
| MD5 |
7f36fbdb8eef84017a7beac14533428e
|
|
| BLAKE2b-256 |
b1ba2f4ea399a3bb29b2e86149d0893c1e386e1065e3c3840918f9c23b7782a4
|