Skip to content
Fermium

App runtime limits

Every limit the app runtime enforces, with its value, the source line and the test that fails if it breaks.

Each row gives the value, the file that sets it and the test that fails when the limit stops holding. A row marked unproven has a value in the code but no test or limits-lab probe that names it yet. Values are read from the code at the commit that added this page; the source column is the place to check them.

The worker README explains the two deadline layers: a compute loop is stopped by epoch interruption at the wall-clock deadline, and a stall inside a host call is bounded by that capability's own deadline.

Run limits

Limit Value Source Proof
Execution deadline 1 to 300 seconds apps/worker/internal/contract/contract.go (MinTimeoutSeconds, MaxTimeoutSeconds) contract_test.go cases "deadline zero" and "deadline too long"; TestDeadlineInterruptsComputeLoop
Compute fuel (backstop behind the deadline) FuelPerSecond per second of deadline apps/worker/internal/wasmrt/runtime.go TestFuelBoundsCompute, TestFuelRateMatchesConstant
Memory per run 128, 256 or 512 MB profile, chosen per app apps/api/src/artifacthost/services/apps.py (PROFILES); contract.go (MemoryProfiles) limits-lab probe "allocate 512 MiB" is refused at the default profile
Concurrent runs per worker 32 by default, FERMIUM_WORKER_CONCURRENCY apps/worker/internal/server/server.go TestBudgetNeverExceedsItsTotalUnderConcurrency covers the memory budget; the slot count itself is unproven
Memory admission budget the container's cgroup limit less headroom, 2 GiB when none is set apps/worker/internal/server/server.go TestBudgetNeverExceedsItsTotalUnderConcurrency
Queued runs per app 8 apps/api/src/artifacthost/services/apps.py (MAX_QUEUE) unproven

Size limits

Limit Value Source Proof
App source 1,000,000 bytes apps.py (MAX_SOURCE); contract.go (MaxSourceBytes) TestSourceSizeIsBounded
Files per app 64 contract.go (MaxFiles) TestSourceSizeIsBounded
Run input 65,536 bytes contract.go (MaxInputBytes) TestInputSizeIsBounded
Run result 1 MiB apps/worker/internal/wasmrt/wasi.go (DefaultLimits) unproven by name
Guest log kept by the worker 256 KiB wasi.go (DefaultLimits) unproven by name
Run log stored by the API 32,768 bytes apps/api/src/artifacthost/services/app_output.py (MAX_LOG_BYTES) test_apps.py and test_app_log_regressions.py assert the stored log stays within it
Capability calls per run 64 wasi.go (DefaultLimits) unproven by name
Bytes per capability call 1 MiB wasi.go (DefaultLimits) unproven by name
Data operations staged per run 200, and 524,288 bytes in all apps.py (MAX_OPERATIONS, MAX_OPERATIONS_BYTES) test_app_data_and_hooks.py asserts the 200 limit; the byte limit is unproven
Webhook delivery body 49,152 bytes apps.py (MAX_HOOK_BODY) test_app_data_and_hooks.py
Webhooks per app 8 apps.py (MAX_HOOKS) test_app_data_and_hooks.py

Network

Limit Value Source Proof
Outbound hosts only those in manifest.network.allow apps/worker/internal/hostcap/hostcap.go limits-lab probes "reach a host not on the allowlist" and "reach localhost"
Private, loopback and metadata addresses refused at connect time hostcap.go TestForbiddenAddress; limits-lab probes "reach cloud metadata" and "reach a cluster-internal address"
Outbound fetch timeout 10 seconds by default server.go, cmd/worker/main.go (FERMIUM_WORKER_FETCH_TIMEOUT_SECONDS) TestNewRequiresFetchDeadline proves a deadline must exist; the 10 s value is unproven
Outbound response body 5 MiB hostcap.go (MaxBodyBytes) unproven
Redirects re-checked per hop hostcap.go unproven by name
Live table read timeout 10 seconds by default server.go (DataTimeout) unproven

Sandbox

Limit Value Source Proof
Packages, Node built-ins, environment, sockets refused apps/worker/internal/wasmrt/wasi.go imports TestLimitsLabHoldsEveryGuardrail, probes "require a third-party package", "require a Node built-in", "read environment variables", "open a socket"
Writes to a table the manifest does not declare refused API data capability limits-lab probe "append to an undeclared table"
One app's globals are invisible to the next isolated per run one Store per invocation TestConcurrentExecutionsAreIsolated

Compute allowance

Included App compute per UTC month is 1 hour on Free, 5 on Starter, 10 on Team, 50 on Business and 200 on Enterprise. The source is INCLUDED_COMPUTE_HOURS in apps/api/src/artifacthost/app_models.py. Each app also has its own monthly spend ceiling, DEFAULT_APP_SPEND_LIMIT, which a workspace administrator can raise. See Plans and limits.

Reading the proof column

TestLimitsLabHoldsEveryGuardrail runs the apps/worker/examples/limits-lab app and fails if a probe that should be refused is allowed. Run it with go test ./... -run TestLimitsLab in apps/worker. Production runs of limits-lab are tracked on the T-102 card, not on this page.