Skip to content

Rate Limits and Quotas

eric edited this page Jul 22, 2026 · 2 revisions

Rate Limits and Quotas

Since 0.16.0 an opt-in limits settings block provides abuse protection for public or multi-tenant deployments (free playgrounds, shared brokers). Entirely inert without the block — no limiting, no overhead. Every limit is independent and optional: absent, 0, or negative means unlimited. Configuration hot-reloads (~1 s).

"limits": {
  "trust_proxy": true,
  "messages_per_second": 20, "message_burst": 60,
  "bytes_per_second": 262144,
  "max_connections_per_ip": 20, "connections_per_minute_per_ip": 60,
  "max_registrations_per_socket": 50, "max_registrations_per_realm": 500,
  "max_subscriptions_per_socket": 50, "max_subscriptions_per_realm": 500,
  "max_queued_per_realm": 1000,
  "realms_per_hour_per_ip": 10,
  "max_pending_authorization_requests": 1000,
  "realms": { "org:vip": { "messages_per_second": 200 } }
}

The limits

Limit Scope Protects against
messages_per_second (+ message_burst) per socket, token bucket publish floods
bytes_per_second (+ bytes_burst) per socket bandwidth abuse; chunked large messages count as chunks arrive
max_connections_per_ip per IP, concurrent socket floods
connections_per_minute_per_ip per IP, rate reconnect hammering
max_registrations_per_socket / _per_realm producers + consumers memory exhaustion via registrations
max_subscriptions_per_socket / _per_realm subscriptions same, via subscriptions
max_queued_per_realm durable queue depth storage abuse (memory/sqlite backends; check + enqueue serialized per realm so bursts can't race the cap)
realms_per_hour_per_ip POST /api/realms realm churn spam
max_pending_authorization_requests global flooding the one unauthenticated allocation

Per-realm overrides under limits.realms beat the globals — the knob for tiered service (a paid realm gets higher rates on the same broker).

Behavior on breach

  • Soft breaches drop the message/operation and send RATE_LIMITED { code: 429, reason, retry_after } — emitted at most once a second per socket, so the notification itself cannot amplify a flood.
  • Connection-level breaches send the notice, then disconnect.
  • POST /api/realms answers HTTP 429 with retry_after.
  • Every enforcement increments tyo_mq_rate_limited_total{reason} on the Observability HTTP API metrics endpoint — watch abuse patterns there.

Behind a reverse proxy

Set trust_proxy: true so per-IP accounting uses the first X-Forwarded-For hop instead of the proxy's address. Only enable it when a trusted proxy actually sets the header. Pair the app-level limits with proxy-level ones (nginx limit_conn / limit_req) as the first line of defense.

Public playground recipe

Free-for-all server that stays healthy: the block above as-is, plus memory storage with a short default_ttl, a modest maxHttpBufferSize (payload size cap), Ephemeral Realms for self-serve isolation, and auth enabled with an open default realm. See Server Configuration.

Give the provisioning service an ephemeral_only management token (0.16.1) so it can never mint permanent realms, whatever it asks for:

"management_tokens": [
  { "token": "<random>", "realm_prefix": "trymq:", "ephemeral_only": true, "max_ttl": "7d" }
]

Every realm created through POST /api/realms with that token is forced ephemeral, with requested TTLs capped at max_ttl — the cleanup guarantee holds even if the provisioner is buggy or its token leaks.

Clone this wiki locally