Rate limits and query cost
Current status
The public GraphQL APIs do not currently enforce a published per-key rate limit, and
they do not return rate-limit headers or an extensions.cost budget on responses.
There is no documented max query depth or complexity today. If and when limits are
introduced, they will be documented here and announced in the
changelog before enforcement.
This does not mean "unlimited" — treat the platform as a shared service and design for back-pressure:
- Back off on errors. On
INTERNAL_SERVER_ERRORor a transport failure, retry with exponential backoff and jitter. Do not tight-loop retry. - Do not blind-retry economy mutations.
createCheckoutand similar mutations are not idempotent yet, so an aggressive retry can double-create. See Error codes. - Batch reads with pagination (see Pagination) instead of many tiny requests.
Calls to your ck-exec code
Calls to your app's ck-exec code do not go through GraphQL, and they are
limited: a player may make 120 calls per 10 seconds to an app on one execution host. A
call over it is refused with Busy, and its message starts rate limited and says how
long to wait. The limit is kept per host, so a player connected to hubs on two hosts has
120 on each, and calls between instances don't count.
A player also holds at most 16 connections to one app through a host; the 17th is
answered HTTP 429 before any socket opens. An app runs as many instances at once as its
organization's funding allows (16 while it cannot be charged, 16,384 once it can),
mods included, and a call that would start another is answered Unavailable. One player's
own calls hold at most 64 of them at once (ck-exec 0.17); past it their next new key is
answered Unavailable while other players still place. A text
message closes the connection, because the protocol is binary. See
call limits.
Realtime (UDP) cost model
The realtime path is best-effort UDP and is governed by a spatial fan-out model rather than a request quota:
- Each spatial message carries a
distance(0–8 chunks, Chebyshev) and adecayRate(0–5) that together bound how far and how often it replicates to nearby clients. Choose the smallestdistanceand an appropriatedecayRatefor your gameplay to limit amplification. See Wire formats for the decay algorithms. - The server coalesces outbound messages into bundles (~1 ms window), so a client should
expect batched delivery and parse
MESSAGE_BUNDLEs. Clients may coalesce the same way (replication server v0.27.0+; the SDKs do it by default): several requests in one datagram are charged once for the datagram's wire bytes and counted once per accepted message. sequenceNumberis auint8that wraps at 255 and is correlation only — it is not a flow-control or idempotency mechanism.- Per-session send-rate limit (replication server v0.28.0+). Each authenticated
session may send a sustained 500 messages/second with bursts up to 1,000
(a token bucket per session; every member of a
MESSAGE_BUNDLEcounts as one). Messages beyond that are dropped silently — noGENERIC_ERROR_MESSAGE, because a reply would let a flooder amplify — so if your client sends bursts well above real gameplay rates (voice ~50/s, video ≤60/s, actor updates ~20/s) and sees gaps, check your send rate before suspecting the network. The limit is spent only by messages that already passed session and HMAC checks; unauthenticated traffic cannot consume a real session's budget.
Quotas (a different concept)
Per-org/app usage quotas (e.g. metered service limits) are a billing/entitlement
concept, not a transport rate limit. Query the effective quota for a metric with the
Management API effectiveQuota, and see
Shared environment & billing.
Exceeding a quota surfaces as a quota error on the affected operation, not as a
transport 429.
One shaping cap does behave like a rate limit and is worth knowing about: an unfunded free app's egress is soft-capped at roughly 1 MB/s. Funding the org wallet or enabling auto-billing lifts it — buying a capacity reservation does not. Once an organization can be charged, CK does not rate-limit its egress, and spend is bounded by the caps you set rather than by a throughput ceiling.