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.For the composed one-switch experience, see Reliability Preset. This page documents the admission-control knob in isolation.
Admission control bounds concurrent inbound runs. For a bound on request rate per identity, see Gateway Rate Limit.
Quick Start
For a one-switch preset that turns on admission with sensible defaults alongside graceful drain, see Gateway Reliability Presets.
1
Simple Usage
Cap aggregate concurrent runs with a single parameter:
2
With Configuration
Add a wait queue and choose what happens when the queue is full:
How It Works
Configuration Options
The three fields live onGatewayConfig (read from praisonaiagents/gateway/config.py):
Precedence: CLI flags → YAML → Python defaults.
Python
YAML (gateway.yaml)
CLI
Common Patterns
Production multi-tenant bot — explicit busy ack under load; no OOM risk; no provider 429 storm:shed_oldest can’t evict a live waiter, the newcomer is rejected rather than overfilling the queue:
Observability
BotOS.admission_stats exposes live counters without any extra setup:
rejected alongside your LLM provider’s 429 rate. When both rise together, raise max_concurrent_runs. When only rejected rises, deepen queue_depth or switch to overflow_policy="queue".
Memory-aware admission
Set one number —max_rss_mb — and the gateway queues turns under soft RSS pressure and sheds them under hard pressure, before the OOM killer fires. Zero deps, no new subsystem — the same admission gate that enforces the concurrency ceiling folds a memory decision into every admit().
MemoryPressurePolicy sheds new turns under pressure; see Gateway Memory-Pressure Eviction for reclaiming memory from idle warm caches before the OOM killer fires.Quick start
- Python (single knob)
- YAML
- Explicit ladder
The pressure ladder
Given a sample’s resident set size (rss_mb), the policy decides:
* Memory-only mode caveat. With no concurrency ceiling (
max_concurrent_runs=0), there is no slot to wait on, so a soft-pressure QUEUE degrades to ADMIT — real wait-queue backpressure needs a concurrency ceiling alongside max_rss_mb. The hard threshold always REJECTs regardless, which is what prevents the OOM kill.
Memory-aware configuration
Choosing values
Small always-on host (a $5 VPS)
Small always-on host (a $5 VPS)
Set
max_rss_mb at ~70–80% of the box’s RAM ceiling minus other resident daemons. Example: on a 1 GiB VPS running only the gateway, max_rss_mb: 700 gives a ~630 MiB soft threshold — bursts queue, sustained pressure sheds, and the OOM killer stays quiet.Containerised deployment with a memory limit
Containerised deployment with a memory limit
Set
max_rss_mb to ~80% of the container’s memory limit. The pressure ladder then queues before the kernel starts reclaiming pages aggressively, preserving observability and giving the graceful-drain window a chance to complete in-flight turns.Large host combining concurrency + memory
Large host combining concurrency + memory
Combine
max_concurrent_runs (concurrency ceiling) with max_rss_mb (memory ceiling). Concurrency handles CPU-scaled bursts; memory handles per-turn resident growth (large tool outputs, long transcripts). Either dimension can shed independently.Development / test (off)
Development / test (off)
Default
max_rss_mb=0 disables memory-aware admission entirely. admit() is bit-for-bit as before — the exact behaviour of every release prior to 2026-07-27.Sampler behaviour
The wrapper samples process RSS on a lightweight cadence:- Preferred:
psutil.Process().memory_info().rss— a live, monotonic reading. Enabled automatically ifpsutilis installed. - Fallback: stdlib
resource.getrusage(RUSAGE_SELF).ru_maxrss— a peak (not live) reading, good enough to catch a climbing leak. Kilobytes on Linux, bytes on macOS/BSD; the sampler normalises to MiB. - Self-disable: if the platform can report neither (Windows without
psutil, exotic runtimes), the sampler emits a singleAdmissionGate: resource sampling unavailable on this platform; memory-pressure admission disabled.warning and thereafter returns arss_mb=Nonesample. The policy admits onNone— the monitor never crashes the gateway it protects.
Memory observability
admission_stats gains a max_rss_mb field so operators can confirm the ceiling is wired end-to-end:
stats() surfaces only the configured ceiling, not a rolling RSS window. For historical RSS for capacity planning, scrape psutil.Process(<pid>).memory_info().rss or your existing container / host metrics pipeline.Best Practices
Start with max_concurrent_runs ≈ 2× expected steady-state
Start with max_concurrent_runs ≈ 2× expected steady-state
Set
max_concurrent_runs to roughly twice your expected concurrent-user baseline. Watch admission_stats.rejected — if rejections are non-zero under normal load, raise the ceiling.Default to overflow_policy='reject' for multi-user deployments
Default to overflow_policy='reject' for multi-user deployments
Silent unbounded queueing under load is harder to debug than an explicit busy ack.
reject surfaces pressure immediately and lets users retry on their own schedule.Pair with flow control for full gateway protection
Pair with flow control for full gateway protection
Admission control bounds inbound concurrent runs; flow control bounds outbound send throughput and per-session inbox depth. Production gateways usually want both.
Leave the gate off only for single-user or local dev
Leave the gate off only for single-user or local dev
max_concurrent_runs=0 (the default) disables the gate entirely — every inbound turn runs immediately. Suitable for local development or single-operator deployments where there is no shared provider quota to protect.Related
Memory-aware admission
Queue under soft RSS pressure, shed under hard pressure — before the OOM killer fires
Memory-Pressure Eviction
The eviction-side sibling — reclaim memory from idle warm caches before the OOM killer fires
Gateway Reliability Presets
One switch that turns on admission + graceful drain with sensible defaults
Gateway Flow Control
Outbound counterpart — bounded inboxes and slow-consumer disconnect
Gateway Rate Limit
Bound inbound turns per identity/scope with a sliding window or custom limiter
Gateway Overview
Full gateway architecture and feature index

