Skip to content

Limits

View as Markdown

Daytona enforces three kinds of limits: sandbox limits, which cap the resources a single sandbox can reserve, organization limits, which cap how many sandboxes and image builds an organization can hold at once, and rate limits, which cap how many API requests a project can make within a time window. For information on spending and wallet management, see billing.

Sandbox limits cap the CPU, memory, and disk a single sandbox can reserve. The limits apply per sandbox, not as a shared pool across the organization.

ResourceUnitDefaultMinimumMaximum
CPUvCPU0.1250.12516
MemoryMiB1024512 (when set explicitly)32768
DiskMiB51210240 (when set explicitly)262144

A create request that reserves more than the maximum on any axis is rejected with a 400 error that names the exceeded cap. Requests below the minimum are raised to the minimum. Guaranteed CPU is also raised to at least one core per 4 GiB of guaranteed memory. A sandbox may additionally set per-sandbox limits on vCPUs (between 1 and 16), memory in MiB (between 256 and 32768), and disk in MiB (between 512 and 262144), which can only lower the boot shape below the platform maximum. See sandbox resources.

Organization limits cap the number of sandboxes and image builds across every project in an organization. Each limit is set per organization; an unset limit imposes no cap.

LimitWhat it countsChecked on
max_concurrent_vmsSandboxes that hold or are about to hold compute: pending, building, booting, running, pausing, stopping, or deletingCreate, fork, snapshot restore, start, resume
max_total_vmsConcurrent sandboxes plus stopped and paused sandboxes. Deleted and failed sandboxes do not countCreate, fork, snapshot restore
max_concurrent_buildsImage builds that are pending or buildingImage build

Rate limits control how many API requests you can make within a fixed 60 second window. Requests authenticated with an API key are counted per project: every API key in a project draws on the same budget, so adding keys does not raise the limit.

Requests are counted per organization with an organization API key, per user from the Daytona Dashboard, and per sandbox with a sandbox-scoped token.

Daytona also blocks a client IP address for a window after repeated requests with invalid credentials. Requests that carry a valid API key are not affected by this block.

Daytona includes rate limit information in the response headers of every authenticated request. The header names carry an authenticated suffix, which identifies the rate limit bucket:

HeaderDescription
X-RateLimit-Limit-authenticatedMaximum number of requests allowed in the time window
X-RateLimit-Remaining-authenticatedNumber of requests remaining in the current window
X-RateLimit-Reset-authenticatedTime in seconds until the rate limit window resets
Retry-AfterTime in seconds to wait before retrying (included only on 429 responses)

Daytona returns HTTP 429 Too Many Requests for the following conditions. The code field in the response body identifies the condition. Use it, not the presence of headers, to decide how to react.

codeCauseRetry
RATE_LIMITEDThe request rate limit for the project, organization, user, or sandbox was exceededWait for the seconds in Retry-After, then retry
RATE_LIMITEDToo many requests with invalid credentials from the same IP address; the message is too many failed authentication attemptsFix the credentials; the block lifts after the seconds in Retry-After
OVERLOADEDThe sandbox creation queue or the organization’s admission queue is at capacity (returned by sandbox create, fork, start, resume, and image build)Wait for the seconds in Retry-After, then retry
LIMIT_EXCEEDEDAn organization limit is reachedStop or delete sandboxes, or wait for builds to finish; the response carries no Retry-After
TOO_MANY_REQUESTSA generic 429 with no more specific codeWait for the seconds in Retry-After when present, then retry

The error response is a JSON object with the following properties:

PropertyDescription
codeThe error code.
messageThe error message.
sourceThe component that produced the error, DAYTONA_API.
retry_after_secondsSeconds to wait before retrying, also sent as the Retry-After header. Present on RATE_LIMITED and OVERLOADED responses.
limitOn LIMIT_EXCEEDED responses, the limit hit, such as max_concurrent_vms.
currentThe organization’s current count for limit. Present on LIMIT_EXCEEDED responses.
maxThe organization’s value for limit. Present on LIMIT_EXCEEDED responses.
trace_idThe request trace ID.
{
"code": "RATE_LIMITED",
"message": "request rate limit exceeded; retry after the indicated delay",
"source": "DAYTONA_API",
"retry_after_seconds": 42,
"trace_id": "0af7651916cd43dd8448eb211c80319c"
}

The Python and TypeScript SDKs raise or throw a rate limit error for every 429 response, including the overloaded condition. A LIMIT_EXCEEDED response raises LimitExceededError, a subclass of the rate limit error that also exposes limit, current, and max. All SDK errors expose the HTTP status code, the error code, and the message:

from daytona import Daytona
from daytona.v2 import LimitExceededError, RateLimitError
daytona = Daytona()
try:
daytona.v2.create_from_snapshot("my-snapshot")
except LimitExceededError as e:
print(e.limit, e.current, e.max)
except RateLimitError as e:
print(e.status_code, e.code, e.message)
  • The SDK does not retry a 429 response.
  • Read retry_after_seconds on the error for the seconds to wait.
  • The SDK sets retry_after_seconds on rate limited and overloaded errors.
  • RateLimitedError and OverloadedError subclass RateLimitError.
  • A handler can catch each retryable condition separately.
  • e.code is RATE_LIMITED, OVERLOADED, or LIMIT_EXCEEDED.

Handle 429 responses by waiting for the number of seconds in the Retry-After header (or the retry after seconds field in the body) before retrying. If a retry is rejected again, back off exponentially (1s, 2s, 4s, 8s, and so on) instead of retrying at a fixed interval.

Monitor rate limit headers (X-RateLimit-Remaining-authenticated and X-RateLimit-Reset-authenticated) to track consumption and throttle proactively before reaching the limit.

Distinguish RATE_LIMITED from OVERLOADED. A RATE_LIMITED response means your project sent too many requests; slow down the caller. An OVERLOADED response means the platform’s sandbox creation queue is full; retry after the delay without reducing your request rate elsewhere.

Do not retry LIMIT_EXCEEDED on a timer. The request succeeds only after the count for the named limit drops below max. Stopping or deleting sandboxes frees concurrent slots; only deleting sandboxes frees max_total_vms slots. Build slots free when image builds finish.

Cache API responses that change infrequently, such as sandbox lists, available regions, and snapshot information, to avoid unnecessary requests.

Avoid tight polling loops for state changes. Poll at an interval within the remaining budget, and monitor your logs for 429 errors to catch rate limiting before it affects users.