Rate Limits
Orphnet Logging applies rate limiting at multiple levels to protect the service and ensure fair usage. Rate limits are enforced via KV-backed counters.
Rate Limit Tiers
Auth Endpoints
All routes under /auth/* use the AUTH preset:
| Setting | Value |
|---|---|
| Limit | 5 requests per minute |
| Identifier | Client IP address |
| Window | 60 seconds (sliding) |
This protects against brute-force login attempts and credential stuffing.
API Endpoints
Routes under /logger/*, /projects/*, and /workspaces/* use the API_DEFAULT preset:
| Setting | Value |
|---|---|
| Limit | Configurable per workspace |
| Identifier | API key or JWT user ID |
| Window | 60 seconds (sliding) |
Workspace administrators can configure custom rate limits through the cascading configuration system.
Playground Sandbox
The playground sandbox has restricted limits to prevent abuse:
| Resource | Limit |
|---|---|
| Log ingestion | 100 logs per hour |
| Log queries | 20 queries per hour |
| Demo API key | sk_demo_playground (18-char prefix) |
The sandbox is reset every 6 hours via a scheduled cron trigger, re-seeding demo data and recreating the demo API key.
Rate Limit Headers
Every response includes rate limit headers:
X-RateLimit-Limit: 60
X-RateLimit-Remaining: 58
X-RateLimit-Reset: 1709812800| Header | Description |
|---|---|
X-RateLimit-Limit | Maximum requests allowed in the current window |
X-RateLimit-Remaining | Requests remaining in the current window |
X-RateLimit-Reset | Unix timestamp (seconds) when the window resets |
Rate Limited Response
When a rate limit is exceeded, the API returns:
{
"success": false,
"data": null,
"error": {
"code": "RATE_LIMITED",
"message": "Too many requests"
},
"meta": {
"timestamp": "2026-03-07T12:00:00.000Z"
}
}HTTP Status: 429 Too Many Requests
Cascading Configuration
API rate limits use a cascading match system with explicit priority:
| Priority | Match | Description |
|---|---|---|
| 1 (highest) | Exact method + exact path | e.g., POST /logger/:id/log |
| 2 | Wildcard method + exact path | e.g., * /logger/:id/log |
| 3 | Workspace default | Per-workspace custom limit |
| 4 (lowest) | Preset default | API_DEFAULT preset |
The RateLimitService resolves the applicable limit using this cascade. If no custom configuration exists for a workspace, the preset defaults apply.
Rate Limit Implementation
Rate limits are tracked in KV with the following pattern:
- Key format:
rate:{identifier}:{window} - Value: Current request count
- TTL: Equals the window duration in seconds
The checkRateLimit function takes { key, limit, windowSeconds } and returns whether the request is allowed. The resolveIdentifier function determines the identifier (IP for auth, API key/user for API).
Client IP Resolution
The getClientIp function extracts the client IP from request headers in this order:
CF-Connecting-IP(Cloudflare)X-Forwarded-For(first IP)- Falls back to a default
Rate Limit Violations
Rate limit violations are logged asynchronously via c.executionCtx.waitUntil() to avoid blocking responses. The RateLimitService.logViolation method records violations to the queue for analysis.
Best Practices
Client SDK
The client SDK handles rate limits gracefully:
app.use('*', createLoggingMiddleware({
apiUrl: 'https://api.logvista.orph.dev',
apiKey: 'sk_your_key',
onError: (err) => {
// Rate limit errors are passed here
if (err.message.includes('429')) {
console.warn('Rate limited, logs will be retried on next batch')
}
},
}))BatchTransport
Use BatchTransport to reduce request volume and stay within limits:
const transport = new BatchTransport({
apiUrl: 'https://api.logvista.orph.dev',
apiKey: 'sk_your_key',
maxBatchSize: 50, // Batch more entries per request
flushIntervalMs: 10000, // Flush less frequently
})See Also
- API Reference -- Endpoint overview with rate limit summary
- Error Codes --
RATE_LIMITEDerror code details - Configuration -- Environment and binding setup