Rate Limiting & Caching
Rate limits
EdgeFlags applies per-token rate limiting with minute-based sliding windows.
| Endpoint type | Limit | Examples |
|---|---|---|
| Evaluation | 10,000 req/min | GET /api/v1/flags/:key, POST /api/v1/evaluate |
| Management | 1,000 req/min | POST /api/v1/flags, PUT /api/v1/configs/:key, etc. |
Rate limit headers
Every authenticated response includes rate limit headers:
| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests per minute for this endpoint type |
X-RateLimit-Remaining | Remaining requests in the current window |
X-RateLimit-Reset | Unix timestamp (milliseconds) when the window resets |
When rate limited
A 429 Too Many Requests response is returned with:
{ "error": "Rate limit exceeded", "code": "RATE_LIMITED"}The response includes a Retry-After header with the number of seconds to wait before retrying.
Caching
EdgeFlags uses HTTP caching headers and ETags on read endpoints.
Cache-Control
| Endpoint | max-age | stale-while-revalidate |
|---|---|---|
GET /health | 10s | 30s |
GET /api/v1/flags/:key | 10s | — |
GET /api/v1/flags | 30s | — |
GET /api/v1/configs | 60s | — |
GET /api/v1/configs/:key | 60s | — |
GET /api/v1/segments | 30s | — |
GET /api/v1/segments/:key | 30s | — |
GET /openapi.json | 3600s | 86400s |
ETags
Cached responses include an ETag header (SHA-256 based). Send If-None-Match with the ETag value to get a 304 Not Modified response if the data hasn’t changed:
# First request — get the ETagcurl -v -H "Authorization: Bearer $TOKEN" \ "https://edgeflags.net/api/v1/flags/dark_mode"# < ETag: "a1b2c3d4e5f6a7b8"
# Subsequent request — use If-None-Matchcurl -H "Authorization: Bearer $TOKEN" \ -H 'If-None-Match: "a1b2c3d4e5f6a7b8"' \ "https://edgeflags.net/api/v1/flags/dark_mode"# < HTTP/2 304Optimistic concurrency control
Write endpoints (PUT) support optimistic concurrency via If-Match. This prevents concurrent updates from overwriting each other.
How it works
- Read a resource and note its
versionfield - Send your update with
If-Match: "{version}" - If the version matches, the update succeeds and the version increments
- If another update happened in between, you get a
409 Conflict:
{ "error": "Version conflict", "code": "CONFLICT", "details": { "current_version": 3 }}Example
# Step 1: Read the current flagcurl -H "Authorization: Bearer $TOKEN" \ "https://edgeflags.net/api/v1/flags" | jq '.flags[0].flag.version'# 2
# Step 2: Update with If-Matchcurl -X PUT \ -H "Authorization: Bearer $TOKEN" \ -H "Content-Type: application/json" \ -H 'If-Match: "2"' \ -d '{ "enabled": false }' \ "https://edgeflags.net/api/v1/flags/dark_mode"If-Match is optional — if omitted, the update always succeeds regardless of the current version.
Supported on: flags (PUT /api/v1/flags/:key), configs (PUT /api/v1/configs/:key), and segments (PUT /api/v1/segments/:key).