How an invocation works
A walk through one call, to explain the limits, the error codes and the timing you observe.
1. The path of a call
The gateway and the functions service talk over a message bus. A message on that bus has a size limit, which is why a request or a response above about 256 KiB does not go through: see limits.
2. Inside the runtime
- One worker per call. The edge runtime starts a new isolated V8 worker for each invocation, with the memory limit and the timeout of the function. Nothing in memory survives from one call to the next: do not keep state in a variable. Use your database or Storage.
- Code is cached for a few seconds. The runtime keeps the code and the limits of a function for 5 seconds and drops them when you deploy. Variables are read on every call.
- Your request is rebuilt. The runtime creates the request you described (
method,path,headers,body) and hands it to yourDeno.servehandler. A function therefore behaves like any HTTP server. - The runtime enforces the timeout. When
timeout_secselapses, it cancels the worker; the caller sees an error after about that delay. - WASM functions run inside the service itself, with limits on memory, time and instructions. A WASM function can report log lines, which appear in the
logsfield of the response; a Deno function cannot.
3. The envelope and raw mode
The service has two ways to return your function's answer, chosen by the X-Aurabase-Invoke-Mode request header.
| Envelope (default) | Raw (raw) | |
|---|---|---|
| HTTP status | Always 200 | The function's own status |
| Body | { data: { status, headers, body, logs, duration_ms }, meta } | The function's bytes |
| Content | JSON or UTF-8 text | Anything, including binary |
| Used by | responseType: 'json', the Studio | 'text', 'blob', 'arrayBuffer', direct HTTP |
The envelope exists so that one JSON response can carry the status, headers and duration of the call. Its limit is that bytes cannot travel in JSON: this is why a binary response needs raw mode. The SDK chooses the mode from responseType.
In raw mode the service adds x-aurabase-invoke-origin: function to the answers of your function. An error that comes from the gateway or the runtime does not carry it. This is how the SDK separates FunctionsHttpError (your function answered) from FunctionsRelayError (the platform failed).
4. Time, metering and failures
Three timeouts are nested so that none ends before the one inside it:
The service waits for the runtime for timeout_secs plus a margin. Because the runtime cancels the worker at timeout_secs, you normally see an error from the function at that moment, and a 504 TIMEOUT only if the runtime itself stops answering. A 504 therefore means that the function was started and may have had effects: do not repeat a non-idempotent call blindly.
Metering and quota:
- Before the call, the service reserves one invocation from the plan quota. If the quota is exhausted, the call stops here with
403. - After the call, it records the invocation and its duration in milliseconds.
- If the call fails before your function answers, the reservation is released and nothing is counted.
5. What follows for your code
- Keep each call short and stateless. For long work, enqueue a job.
- Keep requests and responses small; put files in Storage and pass a reference.
- Make functions idempotent: a retried job, a client retry after a network error or a duplicated cron delivery can run your code twice.
- Authorise on the platform's identity headers, because they are the only values the caller cannot forge. See security.
- Measure your own latency: each call pays for the start of a worker. A minimal function reported
duration_ms: 74on a local stack.