Function handler reference
What a Node.js function handler receives and returns, the answers the platform gives on its behalf, its time limit and its environment.
This page describes the Node.js runtime, the one that functions can be built for from the portal today — see Runtimes.
The handler
The code is saved as handler.js and loaded as an ES module on Node.js 22. The runtime calls the
module's default export — or, when there is none, an export named handler, Handle or run —
with a request and a context, and sends back what it returns:
export default async function (req, ctx) {
ctx.log(`${req.method} ${req.path}`);
const name = req.query.name ?? req.body?.name ?? "World";
return { status: 200, body: { message: `Hello, ${name}!` } };
}- Write JavaScript. Type annotations are not compiled away, so TypeScript-only syntax makes the function fail when it starts.
- The function is one file: only Node.js's built-in modules can be imported.
- A module that has no function to call makes the function fail when it starts.
The request
| Field | Contents |
|---|---|
method |
The HTTP method, for example GET |
path |
The whole path, route included: /hello, or /hello/orders/42 for a path below the route |
query |
The query parameters as strings; for a parameter given more than once, the last value |
headers |
The request headers, with lower-case names |
body |
The body parsed as JSON when Content-Type contains application/json; otherwise, and when the body is not valid JSON, the body as a string |
rawBody |
The body as a UTF-8 string |
Besides the caller's headers, the function receives X-Stackship-Function-Name,
X-Stackship-Trigger-Type and the X-Forwarded-* headers from the namespace's proxy. A function
with authentication on also receives the caller's identity — see
Who is calling.
The context
| Field | Contents |
|---|---|
functionName |
The function's name |
namespaceName |
Its function namespace |
triggerType |
http, or timer for a scheduled run |
user |
The claims of the caller's token; set only on an HTTP function with authentication on |
log(message) |
Writes a line to the function's log, prefixed with the function's name |
The response
Return an object; every field is optional:
| Field | Default | Meaning |
|---|---|---|
status |
200 |
The HTTP status code |
headers |
none | Response headers. To override the defaults below, use the key Content-Type spelled exactly so: a key such as content-type is sent next to the default instead of replacing it |
body |
empty | A string is sent as text/plain; anything else is sent as JSON |
Returning nothing sends 200 with an empty body. A Buffer is sent as JSON as well, so binary
responses are not supported.
Answers from the platform
These answers come from the runtime or from the namespace's proxy, not from your code:
| Status | Body | When |
|---|---|---|
401 |
{"error": "…"} |
The function has authentication on and the token is missing or not accepted |
404 |
{"error": "No function found at this path.", "availableRoutes": […]} |
No HTTP function's route matches the path |
405 |
{"error": "Method not allowed", …}, with an Allow header |
The function does not accept the method |
500 |
{"error": "Internal function error"} |
The handler threw an error; the error itself is in the function's log |
503 |
{"error": "Function '<name>' is stopped.", "status": "stopped"} |
The function was stopped through the proxy's management interface — see How a request reaches a function |
504 |
{"error": "Function cold start timeout", …} |
A sleeping function did not start within 30 seconds |
504 |
{"error": "Function timed out", "timeoutSeconds": 300} |
The handler ran longer than its time limit |
Time limit
A handler has 300 seconds. After that the caller gets 504, but the handler is not stopped: it
keeps running in the background. To shorten the limit, set the environment variable
STACKSHIP_TIMEOUT_SECONDS on the function. The proxy gives up on a call when nothing has passed
between it and the function for 310 seconds. The runtime sends the answer only when the handler
returns, so a limit above about 310 seconds has no effect.
Environment
A function receives the namespace's and its own environment variables, and these from the platform:
| Variable | Value |
|---|---|
PORT |
8080 |
STACKSHIP_FUNCTION_NAME |
The function's name |
STACKSHIP_FUNCTION_NAMESPACE |
Its function namespace |
STACKSHIP_TRIGGER_TYPE |
http or timer |
STACKSHIP_ENTRYPOINT |
handler.js |
STSH_<NAME> |
One per secret reference — see Read the values in your code |
STACKSHIP_IDENTITY_RESOURCE_UID, STACKSHIP_IDENTITY_TOKEN_ENDPOINT, STACKSHIP_IDENTITY_POD_TOKEN_PATH |
The namespace's managed identity — see Use a managed identity in code |
Timer runs
A timer function is called with a POST to / and a JSON body describing the run; ctx.triggerType
is timer. See What a run receives.