Most of Queen’s limits exist to keep one request from costing everyone else: a body cap, a ceiling on what one log entry may carry, a budget on how much a KV call may read. Few of them are about the data itself. The broker puts no cap on partitions per queue, on queues per tenant, or on how long a partition’s history may grow: your disk and your memory bound those, and a proxy plan can cap them per tenant (see tenants).
Each limit below comes with the setting that moves it, when there is one, and the file that applies it. The values are the defaults of server 2.0.1; the full list of settings is on configuration.
Requests
| Limit | Default | Setting | Applied in |
|---|---|---|---|
| Request body | 64 MiB | QUEEN_MAX_BODY_BYTES |
server/src/handlers/raft.rs |
| One planned command (a push to one partition, a KV call, a timers call, a positions list) | 96 MiB | QUEEN_RAFT_ENTRY_MAX_BYTES |
server/src/rsm/planner/push.rs |
Message payload |
any JSON value, inside the two limits above | server/src/rsm/facade/real.rs |
|
| Items per push | no count limit | server/src/rsm/facade/real.rs |
|
transactionId |
65,535 bytes | server/src/rsm/facade/real.rs |
|
| Deadline of a push | 30 s, at most 60 s | POP_DEFAULT_TIMEOUT_MS |
server/src/handlers/raft.rs |
| Deadline of an ack, a lease extension or a transaction | 30 s, at most 60 s | QUEEN_STMT_TIMEOUT_MS |
server/src/handlers/raft.rs |
The pushes to one partition travel as one command, so items for one partition that together exceed
the command limit are refused, and those items answer status: "error" in the 201 body.
Names
| Name | Rule | Applied in |
|---|---|---|
| Queue, partition, consumer group | No character rules. Tenant + queue + the longer of partition and group: at most 447 bytes. The tenant id is 36 bytes, which leaves 411 for the queue and the longer of the other two. Over it: 413 name_too_long. |
server/src/rsm/facade/mod.rs |
| Partition, when not named | Default |
server/src/rsm/facade/real.rs |
| Consumer group, when not named | __QUEUE_MODE__ (queue mode) |
server/src/rsm/facade/real.rs |
| Queue namespace and task, for a queue a push creates | The first and second dot-separated parts of the queue name | server/src/rsm/planner/timers.rs |
KV namespace (ns) |
^[a-z0-9][a-z0-9._-]{0,63}$ |
server/src/rsm/planner/kv.rs |
| KV key | 1 to 512 bytes, no NUL, and tenant + namespace + key within the store’s 511-byte key | server/src/rsm/planner/kv.rs |
| Position metadata | 4096 bytes | server/src/rsm/planner/positions.rs |
Queues, leases and retries
A queue created by its first push (or by a timer firing into it) and a queue created with
POST /api/v1/configure start with different lease times:
| Option | Created by a push | Created by configure |
Applied in |
|---|---|---|---|
leaseTime |
60 s | 300 s | server/src/rsm/planner/timers.rs, server/src/rsm/facade/real/phase2.rs |
retryLimit |
3 | 3 | same |
deadLetterQueue |
on | on | same |
dedupWindowSeconds |
3600 | 3600 | same |
retentionEnabled |
off | off | same |
A pop’s leaseSeconds overrides leaseTime for that pop, and
POST /api/v1/lease/:leaseId/extend extends by seconds, 60 by default. configure merges by
default: an option you leave out keeps its value, and null restores its default. With
"mode": "replace", every option you leave out goes back to its default.
Dedup
| Limit | Default | Setting | Applied in |
|---|---|---|---|
| Dedup window, per queue, checked per partition | 3600 s; 0 turns dedup off; no upper bound |
dedupWindowSeconds on configure |
server/src/rsm/planner/push.rs |
| How long the hashes behind it are kept | the window, and never less than 900 s | QUEEN_RAFT_TXN_WINDOW_MIN_S |
server/src/rsm/maintenance.rs |
| How long a push keeps its index row in memory | the same time, then the row goes even if the message stays (cluster version 6) | QUEEN_RAFT_ROWS_WINDOW |
server/src/rsm/maintenance.rs |
| A committed command answers a retry of its request id | 60 s | QUEEN_RAFT_REQUEST_ID_WINDOW_S |
server/src/rsm/batcher.rs |
Two items with the same (queue, partition, transactionId) in one request store one message,
whatever the window.
Pop and long-poll
| Parameter | Default | Bound | Applied in |
|---|---|---|---|
batch |
200 | none in the broker | server/src/handlers/data.rs |
partitions (wildcard pop) |
1 | 1 to 64 | server/src/handlers/data.rs |
timeout with wait=true |
30,000 ms (POP_DEFAULT_TIMEOUT_MS) |
60 s | server/src/handlers/raft.rs |
A pop that finds nothing before its timeout answers 204.
Through the proxy built into the binary, three timers in one process bound a pop with wait=true.
The broker waits at most 60 s (300 s for an ephemeral pop) and answers 204. The proxy waits
min(timeout, QUEEN_PROXY_LONGPOLL_MAX_MS) plus QUEEN_PROXY_LONGPOLL_MARGIN_MS, 100 s at most by
default, then answers 504 upstream_timeout. The edge waits timeout plus
QUEEN_EDGE_LONG_POLL_GRACE_MS, at most QUEEN_EDGE_LONG_POLL_MAX_MS (310 s), then answers 504
request_timeout. A durable pop always ends at the broker. An ephemeral pop that asks for more than
100 s ends at the proxy with a 504, unless QUEEN_PROXY_LONGPOLL_MAX_MS is raised to 300000.
Reads by offset
| Limit | POST /api/v1/fetch |
POST /api/v1/fetch/offsets |
POST /api/v1/partitions/changed |
|---|---|---|---|
| Entries per call | 1024 | 1024 | 1024 |
| Bytes per entry | maxBytes, 1 MiB by default, 1 byte to 8 MiB |
||
| Long-poll | maxWaitMs, at most 30,000 |
none | none |
| Partitions per entry | limit, 1000 by default and at most |
Applied in server/src/rsm/facade/real/phase2/reads.rs and offsets.rs.
KV
| Limit | POST /api/v1/kv and the KV routes |
Inside a transaction | Setting |
|---|---|---|---|
| Value | 64 KiB as compact JSON | the same | QUEEN_KV_MAX_VALUE_BYTES |
| Operations per call | 256 | 64 | QUEEN_KV_MAX_OPS_PER_CALL (routes only) |
| Keys named per call | 1024 | 256 | QUEEN_KV_MAX_KEYS_PER_CALL (routes only) |
getPrefix limit |
100 by default, at most 1000 | not allowed | |
| Bytes read per call | 4 MiB | 4 MiB | |
| Writes of one key per call | 1 | 1 | |
| Expiry | ttlSeconds above 0 or forever: true, required on every put, putIfAbsent and incr |
the same | |
check |
needs cluster format version 5 (503 below it) | the same | |
| Calls per tenant | reads 200/s (burst 400), writes 100/s (burst 200) | not counted | QUEEN_KV_READ_RATE, QUEEN_KV_READ_BURST, QUEEN_KV_WRITE_RATE, QUEEN_KV_WRITE_BURST |
A call over a tenant’s rate answers 429 rate_limited. A tenant’s quota row can set its own rates
and row and byte caps; see tenants.
Locks
A lock is a KV row in the namespace queen-locks, so the KV value, rate and quota limits above
apply to it. The route’s own limits are constants in server/src/locks.rs.
| Limit | POST /api/v1/locks |
|---|---|
| Operations per call | 64, each on a different lock |
Permits of one semaphore (limit) |
1 by default (a lock), at most 1,024 |
| Slots named per call | 4,096 (an acquire counts its limit, a get 1,000) |
| Lock name | 1 to 256 bytes, no control character, no # |
owner |
at most 256 bytes, no control character |
| Lifetime | ttlSeconds, a whole number above 0, required on every acquire and renew; there is no forever |
| Calls per tenant | a call with an acquire, renew or release spends one token of the KV write rate; a call of gets alone, one of the read rate |
A waiting acquire in the SDKs comes back every 100 ms to 1 s, with jitter, and the handles that
renew in the background do so every third of the lifetime.
Timers
| Limit | POST /api/v1/timers |
Inside a transaction | Setting |
|---|---|---|---|
Horizon (delayMs) |
90 days, narrowed by a tenant’s quota | not checked | QUEEN_TIMERS_MAX_HORIZON_S |
| Payload, decoded | 1 MiB | not checked | QUEEN_TIMERS_MAX_PAYLOAD_BYTES |
| Operations per call | 256 | not checked | QUEEN_TIMERS_MAX_OPS_PER_CALL |
| Schedules per tenant | share the KV write rate | not counted | QUEEN_KV_WRITE_RATE |
One (queue, timerKey) per call |
yes | yes |
The leader fires due timers every 50 ms (QUEEN_RAFT_TIMER_TICK_MS), at most 256 timers and 4 MiB
per tick. A fire that fails is retried with a backoff from 1 s to 60 s, and after 5 failed
attempts (QUEEN_SWEEPER_MAX_ATTEMPTS; transient failures are not counted) the timer is
dead-lettered into its queue’s DLQ.
Ephemeral queues
Ephemeral queues live in memory, so their limits are memory budgets. Each is a ceiling a
configure cannot raise.
| Limit | Default | Setting |
|---|---|---|
| Ephemeral bytes per node | 256 MiB; over it, 503 ephemeral_unavailable |
QUEEN_EPHEMERAL_MAX_BYTES |
| Bytes per queue | 16 MiB | QUEEN_EPHEMERAL_QUEUE_MAX_BYTES |
| Messages per queue | 10,000 | QUEEN_EPHEMERAL_QUEUE_MAX_LENGTH |
| Lease | 30 s (at most a day) | QUEEN_EPHEMERAL_LEASE_S |
| Attempts before a message is dropped (there is no DLQ) | 5 | QUEEN_EPHEMERAL_RETRY_LIMIT |
| Idle time before an implicit queue is collected | 300 s; 0 never |
QUEEN_EPHEMERAL_IMPLICIT_IDLE_S |
| Pushed messages per tenant | 5,000/s, burst 10,000 | QUEEN_EPHEMERAL_RATE, QUEEN_EPHEMERAL_BURST |
Items per push or ack call, and pop batch |
10,000 | |
Pop timeout |
300,000 ms | |
| Queue, partition and group names | 512 bytes |
The last three are constants in server/src/handlers/ephemeral.rs.
Retention
| Behaviour | Default | Setting |
|---|---|---|
| Retention of messages | off per queue | retentionEnabled, retentionSeconds, completedRetentionSeconds on configure |
| Retention pass | every 5000 ms | RETENTION_INTERVAL |
| A queue-log reclaim pass: files judged, time, rewrites | 256 files, 200 ms, one rewrite; four times each while the last pass left work | QUEEN_QLOG_RECLAIM_BOOST |
| A partition with no retained message, no dead letter, no live lease and no stream state, unwritten for this long, is deleted. Never sooner than its queue’s dedup window (at least 900 s) | 30 days | PARTITION_CLEANUP_DAYS, or PARTITION_CLEANUP_SECONDS (at least 60) when set; QUEEN_PARTITION_CLEANUP_ENABLED |
| Message traces (on disk, expired at most 512 per step) | 7 days | QUEEN_RAFT_TRACE_RETENTION_S |
A trace whose transactionId or one of its names makes a store key over 511 bytes is answered 400 |
511 bytes | none |
| Disk high-water mark: writes that grow storage answer 507 | 85% | QUEEN_RAFT_DISK_HIGH_PCT (released at QUEEN_RAFT_DISK_LOW_PCT, 80%) |
| Sealed log files whose index is memory-mapped (one that fits a page, about 80 records, is read into memory and takes no map; so is one the kernel refuses to map) | 65,530 maps a process, about 4 TB of log at 64 MiB a file | the kernel’s vm.max_map_count; QUEEN_RAFT_SEGMENT_BYTES |
| A node stops keeping its log for a standby cluster that is behind | when its disk is 80% full, or the standby was silent for 3600 s | QUEEN_LINK_HOLD_DISK_PCT, QUEEN_LINK_HOLD_S |