Each RF3 node admits commands before enqueueing or forwarding them. CommandAdmissionGovernor bounds the count and retained payload bytes of queued and active commands, with separate tenant and principal counts. The scope comes from the node's verified principal catalog, rather than tenant or role claims in the submitted JSON. Multiple API keys for the same principal share its budget.
The default data lane permits 256 commands and 128 MiB of retained payload accounting, with caps of 128 per tenant and 64 per principal. Accounting includes the UTF-16 payload, twice its UTF-8 byte count for serialization/escaping in the Raft envelope and 4 KiB of envelope overhead. This measures the admitted command payload model, not total process RSS or native storage allocations.
Queue ACK/NACK/renew, subscription delivery commands, Orleans membership and dispatch control use an independent reserve: 16 commands and 2 MiB, with eight commands per tenant/principal and a 64 KiB maximum UTF-8 control payload. Processing effects and projection effects use the data lane. Both lanes remain bounded. A single apply worker selects control work first, then selects a waiting data command after at most eight consecutive control commands. Each lane preserves FIFO. An active replication cannot be preempted; the existing replication deadline still applies. Native Raft RPCs use their own transport and do not enter this command queue.
Admission failure returns ResourceExhausted before this attempt takes the command ID or appends a Raft entry. An earlier interrupted attempt with that ID may already have committed; continue using the same ID until its durable outcome is resolved. A follower preserves an explicit authenticated leader admission rejection; an interrupted or malformed leader response remains UnknownWriteOutcome. Once admitted, cancelling the caller's response does not release the reservation or imply that the command was cancelled. The worker releases it only when replication/forwarding completes or fails. Shutdown rejects queued responses with UnknownWriteOutcome and releases their reservations; an active command retains its reservation until its worker exits. Scope counters are removed when their last reservation is released.
Configure a standalone node through KeyLoad:CommandAdmission:<property> or equivalent environment variables, such as KeyLoad__CommandAdmission__MaxRetainedBytes. The AppHost forwards configured values to its three voters. These local admission limits may differ between nodes. Canonical mutation/outbox/transaction limits must remain identical between voters; local throttling never changes the apply decision for an already committed entry.
Cluster administrators can inspect GET /v1/admin/admission or KeyLoadClient.AdmissionStatusAsync, which returns the configured limits and current data/control usage. The endpoint uses the normal authenticated quorum-read path.
Unit tests cover concurrent count/byte limits, tenant/principal isolation, control reservation, bounded scheduling, cancellation and shutdown. A separate Aspire RF3 test exhausts the entire data-byte budget, verifies that catalog writes remain unpublished, and commits dispatch control under the rejected command IDs. Continued routing and that ID reuse prove rejection before canonical acceptance. The normal RF3 suite independently exercises queue and subscription ACK/processing, leader loss, minority rejection and snapshot catch-up.
HttpAdmissionGovernor reserves a node-local request slot before a quorum read or JSON deserialization, then binds tenant/principal counts only after credential verification. Reservations last through response processing. The default data pool has 32 slots and 1 GiB of modeled bytes, with 16 requests per tenant and eight per principal. Query, search, graph traversal and bulk read routes share that pool. Each heavy read reserves 64 MiB of modeled working space; other data requests reserve 8 MiB. Accounting adds four times the admitted body size and 4 KiB of overhead. This is concurrency and accounting control; it does not measure or cap every allocation or process RSS.
Queue/subscription delivery and dispatch routes have an independent 16-slot, 8 MiB control pool, with eight requests per tenant/principal. Processing effects remain in the data pool. Public data bodies are limited to 8 MiB and control bodies to 64 KiB. A known Content-Length reserves that framing bound; an unknown/chunked length reserves the full route body cap. Kestrel enforces the cap while reading. Declared and chunked oversize rejections return typed ResourceExhausted before submitting a command. Native Raft, internal peer forwarding and health routes use their own paths and do not spend the public HTTP pool.
Configure KeyLoad:HttpAdmission:<property> or matching environment variables; the AppHost forwards these settings. AdmissionStatusAsync includes HTTP node accounting and verified scope accounting. The node accounting uses a synthetic ingress scope before authentication; actual tenant/principal scope counts are in VerifiedScopes. Limits are local to a voter and do not change deterministic state-machine apply. Unit regressions cover shared read accounting, unverified/verified scope boundaries, reserve independence, cancellation and disposal. An Aspire RF3 regression checks both declared and chunked body limits, then commits control work under each rejected command ID.
Native cache/memtable limits, disk-floor throttling, rebuild/compaction reserves, automatic retention and sustained RSS/endurance qualification remain tracked work. These admission governors alone do not qualify those resources.