The gateway now ships in the
praisonai-bot package. praisonai serve gateway still works exactly as documented here; for a standalone install see praisonai-bot Migration.RateLimitPolicyProtocol lets you plug any rate limiter — per-tenant, Redis-backed, or cost-based — into the gateway’s connection handshake with a single check method. A built-in sliding window policy covers most use cases out of the box.
Quick Start
How It Works
allowed=False maps to ConnectErrorCode.RATE_LIMITED on the wire and sets HelloError.retry_after_seconds so clients know when to retry. Wire details are in Gateway Handshake Protocol.
Imports
API Reference
RateLimitDecision
A frozen dataclass returned by every check() call.
| Field | Type | Description |
|---|---|---|
allowed | bool | True → request passes; False → reject with RATE_LIMITED error |
retry_after_seconds | float | Hint to the client: how long to wait before retrying. Sent as HelloError.retry_after_seconds on the wire. |
RateLimitPolicyProtocol
@runtime_checkable Protocol — any class with a matching check signature satisfies it without inheriting:
SlidingWindowRateLimitPolicy
Config-driven, dependency-free default. Keyed per (scope, identity).
| Option | Type | Default | Description |
|---|---|---|---|
max_requests | int | 0 | Ceiling per (scope, identity) in the window. 0 disables limiting entirely. |
window_seconds | float | 60.0 | Rolling window width in seconds. Must be > 0. |
lockout_seconds | float | 0.0 | Cooldown after ceiling breach. During lockout, every check() returns allowed=False. |
RateLimitPolicy
Backward-compat alias for RateLimitPolicyProtocol. New code should import RateLimitPolicyProtocol.
State Ownership
The built-inSlidingWindowRateLimitPolicy is not internally synchronised and reclaims (scope, identity) entries lazily on the next check.
- Suitable for: bounded, authenticated identity spaces (tenants, endpoint classes, known API keys).
- Not suitable for: unbounded / untrusted identity spaces (raw per-IP keys) — implement
RateLimitPolicyProtocolin the wrapper layer and run periodic reclamation yourself.
Common Patterns
Per-tenant limiter with different quotas
Disable rate limiting (legacy always-allow)
Best Practices
Keep check() fast — it runs on every request
Keep check() fast — it runs on every request
check is called synchronously on the hot path. Avoid network calls inside it. Use a local in-process cache (e.g. a dict + sliding window) and sync to Redis asynchronously.Always return retry_after_seconds when rejecting
Always return retry_after_seconds when rejecting
Clients use
retry_after_seconds to back off correctly. Returning 0.0 on a rejection causes immediate retries and amplifies load. Return a meaningful value (5–60 s).Set max_requests=0 to disable limiting
Set max_requests=0 to disable limiting
max_requests=0 is the default — it passes every request through, identical to having no policy. Use this when you want to add a policy object for future use without enforcing limits yet.Tune lockout_seconds for abusive callers
Tune lockout_seconds for abusive callers
Set
lockout_seconds to apply a cooldown after a caller hits the ceiling. Without a lockout, callers can burst exactly max_requests per window forever by timing their requests carefully.Scope by both identity and scope for multi-platform bots
Scope by both identity and scope for multi-platform bots
The same user may appear across Telegram and Discord. Scope per
(identity, scope) to set per-platform limits, or drop scope to share a single quota across all platforms.Use runtime_checkable for duck-typing
Use runtime_checkable for duck-typing
RateLimitPolicyProtocol is @runtime_checkable — use isinstance(my_policy, RateLimitPolicyProtocol) to verify your custom class satisfies the contract before injecting it.Related
Gateway Handshake Protocol
ConnectErrorCode.RATE_LIMITED and HelloError.retry_after_seconds
Bot Rate Limiting
Messaging platform rate limits (Telegram, Discord, Slack)
Gateway Reliability
One-switch reliability preset for production deployments
Rate Limiter
LLM API rate limiting (requests per minute, token budget)

