Limits reference
Every enforced Easel limit for builds, Functions, requests, Runtime Cache, domains, security, and observability.
This page lists every limit Easel enforces. Where a framework sets its own default, the stricter of the framework and Easel limit applies, so don't infer a limit from a framework default or another hosting provider.
Builds and deployments
| Limit | Value |
|---|---|
| Build duration | 10 minutes |
| Concurrent builds | Hobby 1, Pro 3 per workspace; up to 12 by agreement. See Build queue |
| Build machine CPU, memory | See Build machines |
| Function bundle (zipped) | 250 MB |
| Environment variables | 64 KB total, names and values combined |
| Source: files | 20,000 |
| Source: single file | 50 MiB |
| Source: total size | 250 MiB, after extracting an archive |
| Source archive (gzip) | 250 MiB |
Source limits apply however you upload the source: easel deploy or the
API. A build that runs past 10 minutes fails with a timeout. A build also fails when
the resolved environment variables exceed 64 KB, so keep large files,
certificates, and datasets out of environment variables.
To shrink a function bundle, remove unused dependencies, use framework output tracing, and load large assets from object storage instead of packaging them.
Functions
| Limit | Value |
|---|---|
| Default maximum duration | 30s |
| Maximum configurable duration | 800s; values outside 1–800s are clamped |
| Wait for response headers | 60s from invoke start |
| Wait between body chunks | 30s |
| Memory and CPU | 2 GB / 1 vCPU (Standard), 4 GB / 2 vCPU (Performance) |
| Incoming WebSockets | Not supported; use streaming HTTP or SSE |
Duration covers the whole invocation: your handler, streaming the response
body, and waitUntil / after() work. Returning headers doesn't end it. Set
it per route through your framework; see
Maximum duration. Move work
that can't finish within 800s to a queue or durable worker.
The header and chunk waits abort a stalled invocation early. Each is capped by
the duration budget that remains, so a short maxDuration ends a stall sooner.
Easel also enforces in-function concurrency, response size, temporary filesystem capacity, and outbound connection counts. These values aren't published and can change with runtime configuration, so keep your code safe under concurrent requests on a shared instance. See Function runtime.
Requests and delivery
| Limit | Value |
|---|---|
| Request body size | 10 MiB; the full body must arrive within 30s |
| Header, cookie, and URL size | Enforced; values not published |
| Cacheable response size | 10 MiB after compression; larger responses are served but not cached |
| Minimum size for compression | 256 bytes; smaller responses are sent uncompressed |
| Cache tags per response | No cap |
| Cache tag length | No cap |
| Tags per revalidation request | No cap |
Easel rejects a larger request body with 413 at the edge, before your
function runs. For large uploads, send files from the browser straight to
object storage with signed URLs. Keep cookies small and put large structured
input in a request body instead of the URL.
Keep cache tags short and low-cardinality even without a cap. See Revalidation.
Runtime Cache
| Limit | Value |
|---|---|
| Item size | 2 MiB |
| Tags per item | 128 |
| Tag length | 256 bytes |
| Maximum entry age | 30 days |
| Storage per cache, per region | 64 MiB on Hobby, 128 MiB on Pro |
On Pro, each project has one cache per environment; on Hobby, a workspace's projects share one. See Storage for how Easel evicts entries when a cache is full.
Queues
| Limit | Value |
|---|---|
| Message size | 4 MiB |
| Retention | 60 seconds to 7 days, 24 hours by default |
| Delay | Up to 7 days, and no longer than the retention |
| Lease (visibility timeout) | Up to 60 minutes |
| Messages per receive | 10 |
| Messages per batch publish | 100 |
| Idempotency key | 256 characters, deduplicated for up to 24 hours |
| Topics with messages, per project | 10,000 |
| Consumer groups per topic | 1,000 |
| Messages in flight per consumer group | 10,000 (received and not yet acknowledged) |
Past a limit, the API answers 429 with Retry-After. A consumer group at its
in-flight limit gets only redeliveries until it acknowledges some messages.
Queues run in iad1. See Queues for
delivery and retry behavior.
Domains
| Limit | Value |
|---|---|
| Domains per project or workspace | No plan cap |
| Projects per hostname | 1, across all of Easel |
| Unverified domain or zone holds its name | 7 days |
| Hostname (FQDN) length | 253 characters |
| Label length | 63 characters |
For allowed characters, see Add the domain. For the 7-day rule, see Domain ownership. A project can't have a wildcard domain; see Wildcard domains. A workspace wildcard domain covers names exactly one label under it; see Set up your domains.
Platform API
| Limit | Value |
|---|---|
| Requests per token | 6,000 per minute |
| Idempotency key length | 255 characters |
| Idempotency key kept | 24 hours |
| Scoped token lifetime | 60 seconds to 1 year, and no longer than the token that mints it |
| Projects per scoped token | 100 |
| Token name | 32 characters |
| Upload URL lifetime | 60 to 900 seconds; 900 by default |
| JSON deployment request (inline files) | 10 MiB |
Deployment meta | 20 pairs, keys up to 64 characters, 1 KiB of JSON in total |
| Git metadata header on an archive | 2 KiB |
Hashes per POST /v1/files/missing | 20,000 |
| Environment variables per request | 500 |
| Deployments per page | 20 by default, up to 100 |
| Runtime log and request records per page | 50 by default, up to 200 |
| Usage range | 366 days |
| Webhooks per workspace | 20 |
| Webhook delivery attempts | 8, over about 20 hours |
| Webhook response wait | 10 seconds |
| Webhook response body read | 64 KiB |
A request over the token's rate limit gets 429. A webhook delivery that
doesn't get a 2xx within the wait is retried until the attempts run out.
See Webhooks.
Security
| Limit | Value |
|---|---|
| Custom firewall rules | No published cap |
| Rate limit rules per project | Hobby 1, Pro 40 |
| Rate limit window | 10 seconds to 10 minutes |
| Attack challenge mode verification session | About 1 hour |
| Attack challenge mode work token | About 15 minutes |
| Deployment protection session | About 1 hour |
Firewall and attack challenge mode changes reach every edge region after a short delay, with no redeploy.
Observability
| Limit | Value |
|---|---|
| Chart time windows | 6h, 12h, 24h, 7d |
| Logs time range | 30 minutes to 7 days |
| Metric buckets | 5 minutes (24h or less), 60 minutes (longer) |
| Logs rows per page | Up to a few hundred |
| Function log lines per invoke | 256 |
| Function log line size | 256 KiB |
| Function log output per invoke | 1 MiB |
| OpenTelemetry spans | 1,000 spans and 2 MiB per request; attributes over 64 KiB are dropped |
easel logs --follow poll interval | About 10 seconds |
Easel doesn't publish a retention guarantee beyond the 7-day window. Log and trace delivery is best-effort and never blocks your requests, so don't treat Logs as a complete audit log. To keep data longer, use Export.
When you exceed a limit
- Request body too large: the client gets
413and your function doesn't run. - Duration reached or stalled response: Easel terminates the invocation.
- Build duration or environment variable size: the build fails.
- Runtime Cache pool full: Easel evicts the least recently used entries. A write fails only when eviction can't free enough space.
- Function logs or spans over the cap: Easel drops the excess output.
To find which limit a request hit, look it up by its request ID (X-Easel-Id)
in Logs and its Trace.
Raise a limit
Some limits are fixed. Others depend on your plan or can be raised by agreement. Email hello@easel.sh with the limit name and the failure you're seeing.