Goal
Build and operate a StackShift Functions project as the fastest path to one endpoint, one webhook, one cron, or one worker without learning the platform internals first.Prerequisites
- A GitHub-backed project or Docker image project that contains an
api/directory - Node.js handler files under
api/using JavaScript or TypeScript - At least one healthy node running the Phase 4 agent
Workflow
Create function files under
api/ and export HTTP methods such as GET, POST, PUT, PATCH, DELETE, or HEAD.Add
stackshift.functions.json when you need async, queue, schedule, timeout, retry, or memory configuration.Deploy the project with workload type
functions; StackShift builds .stackshift/functions-runtime.mjs and a functions manifest into the image.Caddy sends public traffic to the agent functions gateway, and the gateway cold-starts the project container only when a request arrives.
Use
@stackshift/functions from inside a function to enqueue async work by function path or explicit queue name.Project layout
A StackShift Functions project is detected from anapi/ directory when the repo does not have a stronger full-stack framework signal. During build, StackShift copies or compiles those handlers into .stackshift/functions/api, writes .stackshift/functions-manifest.json, and starts the generated runtime with node .stackshift/functions-runtime.mjs.
Use file paths to define routes. Static route segments win over dynamic route segments, so api/users/me.js is matched before api/users/[id].js.
Minimal layout
HTTP handlers
Export named HTTP methods from a handler file.HEAD falls back to GET when a dedicated HEAD export is not present. CommonJS-style default objects are also supported after build, but named ESM exports are the clearest path.
api/hello.js
api/users/[id].ts
Function configuration
stackshift.functions.json is optional. Add it when a function needs a non-default timeout, memory size, retry count, async trigger, explicit queue trigger, or schedule trigger. Config keys use source paths from the repo, not compiled .stackshift paths.
- HTTP timeout must be positive and within the supported HTTP limit.
- Async, queue, and scheduled functions may use longer timeouts than HTTP handlers.
- Supported memory values are
128m,256m,512m, and1g. - Retries apply to non-HTTP work and are capped by the platform.
- Use one explicit queue name per function in v1.
background: trueremains supported and maps to the built-in_asyncqueue.
stackshift.functions.json
Async invocation and queues
Use@stackshift/functions when one function needs to enqueue another function for async work. In deployed workloads, the helper submits a durable run through the private StackShift async endpoint so retries and replay stay available after the original HTTP request has finished.
Use invoke(functionPath, payload) for function-to-function async work or enqueue(queueName, payload) when you want a stable queue name for producers outside the target function file. The built-in _async queue backs legacy background: true functions.
Queue work from an HTTP handler
Schedules
Scheduled functions exportrun(context) and must be configured with a schedule. StackShift syncs schedules from the generated manifest after a successful deployment and enqueues durable function runs on the declared cadence. New jobs are scheduled for their next real due time, not forced to run immediately after deploy.
- Supported aliases:
@hourly,@daily, and@weekly. - Supported intervals:
@every 15m,@every 2h, and similar positive durations. - Supported simple cron forms include
*/10 * * * *,0 * * * *, and0 */2 * * *. - When a scheduled function is removed from the manifest, StackShift disables the stale scheduled job.
- Failed scheduled runs appear in the project Runs view and can be replayed from there.
api/cleanup.js
Routing and cold starts
In Phase 4, functions are no longer just a file-based runtime inside an always-running project container. Public requests enter through Caddy, Caddy forwards to the local agent functions gateway, and the gateway starts or reuses the project function container. The generated runtime exposes a health endpoint for readiness, normal HTTP route dispatch, and reserved internal invoke endpoints. The agent tracks idle time, active request count, startup timeout, and max concurrency for each functions deployment, while durable jobs drive non-HTTP retries and replayable execution.- Caddy adds
X-StackShift-Functions-Runtimeso the gateway knows which project runtime to use. - The gateway cold-starts
app_<runtimeID>when the function is inactive and waits for__stackshift/health. - Idle containers are stopped after the configured idle timeout and restarted on the next request.
- Reserved internal invoke paths require
X-StackShift-Internal-Tokenbefore any cold start is attempted.
Environment variables
Most projects do not need to set any functions-specific environment variables. StackShift injects the async helper URL, per-project async token, and project ID during deployment. The runtime still exposes internal invoke defaults for local development and compatibility.PORT: the port used by the generated runtime; defaults to the project runtime port, commonly3000.STACKSHIFT_FUNCTIONS_ASYNC_URL: private StackShift endpoint used by@stackshift/functionsto create durable async runs in deployed environments.STACKSHIFT_FUNCTIONS_ASYNC_TOKEN: private per-project token used to authorize async enqueue requests.STACKSHIFT_PROJECT_ID: injected project identifier used by the helper when submitting async or queue work.STACKSHIFT_FUNCTIONS_INVOKE_TOKEN: private token still used by the internal gateway/runtime invoke path.STACKSHIFT_FUNCTIONS_INVOKE_URL: optional local override for unusual topologies. Leave it unset in normal production; the compatibility default remainshttp://127.0.0.1:$PORT/.stackshift/functions/invokeinside the runtime container.FUNCTIONS_ROOTandFUNCTIONS_MANIFEST: generated runtime paths. Override only for custom runtime debugging.
Production URL guidance
api.stackshift.cloud is the StackShift control-plane API. It is not the public endpoint your users hit, and it should not be used as a browser-facing Functions origin. In deployed workloads, the async helper talks to a private StackShift endpoint using the injected async URL and token while public HTTP traffic continues to flow through your project domain and the functions gateway.
On the current production agent install, Caddy runs as a host/systemd service and can reach the functions gateway on 127.0.0.1:<FUNCTIONS_GATEWAY_PORT>. If Caddy is moved into Docker, the gateway binding and Caddy upstream target must be reviewed together because Docker Caddy cannot use its own 127.0.0.1 to reach the host agent.
- Do not expose
STACKSHIFT_FUNCTIONS_ASYNC_TOKENorSTACKSHIFT_FUNCTIONS_INVOKE_TOKENto browsers, client bundles, or public logs. - Do not point your frontend directly at the private async helper endpoint.
- Do keep normal platform API clients pointed at
https://api.stackshift.cloud/api/v1when they are calling the public StackShift API.
Operational checklist
- Confirm the project workload type is
functionsafter detection or manual override. - Check build logs for manifest warnings about missing configured source files, duplicate queue names, or invalid schedules.
- Check deployment logs for gateway registration, Caddy route updates, and cold-start errors.
- Use the Functions overview for HTTP endpoints, queues, schedules, and runs before dropping down to raw durable-jobs internals.
- Use function logs for
[stackshift-functions]entries including request ID, function path, status, duration, trigger type, run ID, and timeout state. - Replay failed schedule and queue runs or retry failed async runs from the project Runs view.
Expected result
The project runs as a managed functions workload: public HTTP routes are routed through Caddy and the agent gateway, async and queue work is durable, schedules run on their declared cadence, and failed non-HTTP runs can be retried or replayed from the project surface.
Common failures
Related guides
Deploy from GitHub
Use the repository-backed project flow when you want StackShift to detect the app, build from source, and let you override runtime behavior before the first deploy.
Builds, deployments, and logs
Understand the project execution lifecycle: build output, deploy state, rollback behavior, and where to inspect logs.
Project environment, domains, and previews
Configure the project surfaces that most often decide whether a deployment works after it builds, including runtime shape, domains, previews, and storage.
Project troubleshooting
Common project-side failure modes, especially when the app built successfully but does not come up healthy.