Configuration & Limits
This page covers everything around your function's runtime: the environment variables and secrets it can read, the memory and timeout it runs with, the quotas that apply, how you're billed, and the errors you might encounter.
Environment variables
Environment variables let you keep configuration and credentials out of your code. You set them per function, and your function reads them at runtime.
There are two kinds:
| Kind | Set as | Read from | Stored |
|---|---|---|---|
| Plain | a normal variable | ctx.env |
in the clear |
| Secret | marked as secret | ctx.secrets |
encrypted at rest, masked when you view it |
export async function handler(ctx) {
const region = ctx.env.REGION; // plain
const apiKey = ctx.secrets.THIRD_PARTY_KEY; // secret, decrypted for this run
// ...
return { ok: true };
}
Use secrets for anything sensitive
API keys, tokens, and passwords belong in secrets, not plain env vars or your source. Secrets are encrypted at rest and shown masked (••••••) when you inspect the function — so they never leak through the dashboard.
Updating a variable takes effect on the next run — you don't need to redeploy your code.
Memory and timeout
Each function has two performance settings you choose when you create it (and can change later):
| Setting | Default | Range | What it does |
|---|---|---|---|
| Memory | 128 MB | 128 – 1024 MB | How much memory your function gets. More memory also means more CPU. |
| Timeout | 10,000 ms | 1,000 – 60,000 ms | How long your function may run before it's stopped. |
If your function runs past its timeout, the run ends with a timed_out status (and an HTTP 504 for HTTP triggers). If it's doing heavy work, raise the memory — it speeds up CPU-bound code as well.
Right-size for the job
Most functions are happy at the 128 MB / 10 s defaults. Raise memory for data-heavy work, and raise the timeout only if a function legitimately needs longer — a long timeout won't rescue a function that's stuck.
Quotas
To keep things fair and predictable, a few limits apply per app:
| Limit | Default | What happens when you exceed it |
|---|---|---|
| Invocations per minute | 120 | Runs are rejected with quota_exceeded (429). Retry after a short wait. |
| Data calls per minute | 600 | Calls to ctx.appambit.* are rejected with quota_exceeded (429). |
| Concurrent runs | 10 | Extra runs queue until a slot frees up. |
| Compute per day | 3,600 compute-seconds | A daily ceiling on total run time. |
| Statements per batch | 50 | ctx.appambit.batch(...) accepts at most 50 statements. |
| Source size | 5 MiB | A single deploy's index.js must be under 5 MiB. |
Hitting a limit isn't an error in your code
A 429 quota_exceeded means you're going faster than the allowance, not that something is broken. Back off and retry, batch your work, or spread it out.
Billing
Cloud Code is billed on two simple dimensions:
- Invocations — the number of times your functions run.
- Compute — how much memory-time your functions use, measured in GB-seconds (memory in GB × run time in seconds).
A function that uses 128 MB for 500 ms bills roughly 0.125 GB × 0.5 s ≈ 0.06 GB-seconds. Because compute scales with both memory and duration, the two easiest ways to lower cost are to finish faster and to only request the memory you need.
Keep runs short
Every millisecond counts toward compute. Avoid unnecessary waiting, request only the data you use, and return early once you have your answer.
Error reference
Errors surface in two places: as the result of a run, and as a thrown error from a data call.
Run outcomes
Every invocation ends in one of these statuses:
| Status | Meaning |
|---|---|
succeeded |
Your handler returned normally. |
failed |
Your handler threw, or the code couldn't run (for example, no handler export). |
timed_out |
Your handler ran past its timeout. |
For HTTP triggers these map to HTTP status codes — see Triggers → Status codes.
Data-call errors
When a ctx.appambit.* call fails, it throws an Error with a code and status:
code |
Status | Meaning |
|---|---|---|
quota_exceeded |
429 |
Too many data calls this minute. Slow down and retry. |
database_not_linked |
403 |
Your app has no linked database. Link one in the dashboard. |
database_unavailable |
503 |
The database is still provisioning. Try again shortly. |
forbidden_query |
403 |
The SQL statement isn't allowed (see the Database restrictions). |
query_error |
500 |
The database rejected the query (for example, a syntax error). |
cms_error |
404 |
The CMS collection doesn't exist for this app, or another CMS error occurred. |
invalid_token |
401 |
The run's access expired mid-execution — usually a sign a run is taking far too long. |
Catch these and decide what to do — see Writing Functions → Handling errors.
Build failures
When you deploy code that can't be built (a syntax error, for example), the version's build status becomes failed and the build log records why. A failed version can't be activated — fix the code and deploy again.
What's next
-
Examples & Tips
Put it all together with complete, copy-pasteable functions.
-
Writing Functions
Revisit the
ctxobject and the data SDK.