A function is a handler, not a server. Synteq owns the HTTP listener and calls your handler once per request with an event and a context. Deploy it from the browser editor, the CLI, or a GitHub folder.
The handler contract
| Event field | Description |
|---|---|
| The HTTP method. | |
| The request path, without the query string. | |
| The query string, parsed into an object of strings. | |
| Request headers, lowercase keys. | |
| The body decoded as UTF-8 text. | |
| The body as bytes, for binary payloads or signature checks. |
The context has and . The Logs tab searches on the request id, so log it to find a run later.
The return value becomes the response:
| Return value | Response |
|---|---|
| Nothing or | , empty. |
| A string or bytes | , . |
| An object with (or ), , | Sent as-is. A non-string body is sent as JSON. sends a base64 string as raw bytes. Any one of these keys makes the object a response, so wrap data that has its own field in . |
| Any other object or array | , JSON. |
| A (Node.js only) | Sent as-is. |
A thrown error returns with the body . The stack trace goes to the run's log lines.
Node.js 22
Export the handler as the default export or as . The entry file is the first of , , , , , .
export default async function handler(event, context) {
return { hello: "world", path: event.path };
}export default async function handler(event) {
if (event.method !== "POST") {
return { statusCode: 405, body: "POST only" };
}
const payload = JSON.parse(event.body || "{}");
return { statusCode: 201, body: { received: payload } };
}Add a to declare dependencies. If it has no start script, Synteq adds one that runs your handler. If it has one, Synteq treats the function as your own server.
Dependencies are installed once per distinct set and attached to the shared Node.js runtime, so a function with a cold-starts as fast as one without. This applies to packages from the npm registry. A dependency from git, a URL, or a local path gives the function its own image instead. Packages that ship prebuilt native binaries, such as , work. Commit a to pin the exact versions Synteq installs.
Python 3.12
Define a module-level (or ). The entry file is the first of , , , . The event and context are dicts with the same keys. Add a for dependencies; they are installed for Python 3.12 once per distinct set and attached to the shared runtime, so they add nothing to your cold start. This applies to packages from PyPI. A URL, VCS, or local-path requirement gives the function its own image instead. Packages with compiled extensions work.
def handler(event, context):
return {"hello": "world", "path": event["path"]}Your own server or Dockerfile
An upload with a is built as-is, in any language. A recognised project file ( with a start script, , , , and others) is built with the same zero-config builder Apps use. In both cases your server listens on (default ), sees raw HTTP, and the handler contract does not apply.
Use a Dockerfile when a dependency needs a system library the shared runtime does not carry. needs , for example, and a cannot install it; a Dockerfile that runs before can. A function built from a Dockerfile runs on its own image rather than the shared pool, so its cold start is the time your image takes to start listening, typically 1–2 seconds.
The folder name is reserved. Uploads containing it are refused.
Create a function in the portal
- On the Functions page, click New Function.
- Enter a name. The hostname preview updates as you type. The first available location is preselected, and the runtime size is chosen for you when your plan pins one.
- Choose how to ship: Write code (opens the editor with a starter handler), Connect GitHub, or Use the CLI (shows the commands to run once the function exists). Click Skip to create an empty function.
- Pick a Runtime if your files do not imply one. implies Node.js; implies Python.
- Optionally add environment variables and cron triggers.
- Click Done. The button reads Skip and finish when you add no triggers.
If the organization has no payment method, the wizard asks for one. If you edited the starter code, the first deploy starts when you finish. An unchanged starter is not deployed.
Deploy from the editor
The Overview tab is an editor with a file tree.
| Control | Description |
|---|---|
| Files | Create, rename, and import files and folders; download the set as a zip. The entry file cannot be deleted. |
| Drafts | Edits autosave as a draft ("Draft saved") that everyone on the team sees. It does not go live until you deploy. Discard changes reloads the deployed version. |
| Show diff | Compares working files with the deployed version, file by file. |
| Deploy | Builds from the working files. Disabled, with the reason, when nothing changed, every file is empty, or the source is over the limits. One build runs at a time. |
A deploy moves through the build (pending, building, succeeded) and then the release (starting, health gate, live). A failed attempt stays on the Versions tab with its build log.
Deploy from the CLI
From an empty directory:
synteq login
synteq function init my-fn
synteq function deploycreates the function (or reuses one with that name), writes a starter handler if there is no entry file or Dockerfile, and links the directory so later commands need no . Use , , or to link without writing a file.
uploads the directory and follows the build and release. Ctrl-C stops watching; the deploy continues. Use in scripts; it returns the build as soon as it starts. With , the command prints the build and the release as JSON.
The CLI uploads text files only and prints every skipped file with its reason:
- Files with a NUL byte in the first 8 KB are treated as binary.
- , , , , , , , , , , and are skipped at any depth.
- files are never uploaded. Set variables with instead.
- Patterns in a file (gitignore syntax) are skipped.
- Paths are limited to 255 characters, with no segments. Symlinks are not followed.
Uploads over the source limits are refused, naming the largest files. Put large assets behind a URL or use a Dockerfile. See CLI reference for all flags.
Deploy from GitHub
A function can follow one folder of a GitHub repository. Set it up from Connect GitHub in the wizard, or under Settings → GitHub.
- Click Connect GitHub and install the Synteq GitHub App on the account that owns the repository. If a repository is missing later, use Repository missing? Grant the app access.
- Pick the account, repository, and branch.
- Pick the folder that holds the handler. Folders with no recognised entry file are flagged.
- Click Connect and deploy. The branch head deploys right away.
Each push that changes something inside the folder deploys a new version; other pushes are ignored. With Auto-deploy off, a push lands in the editor as a draft, and you deploy it from there. The Activity tab records each push deploy, and why a push could not deploy. Disconnecting keeps the current version.
Environment variables
The Environment tab holds the variables your handler reads from or .
Each variable has a name, a value, a kind, and an optional note. Values are encrypted at rest. Renaming a variable keeps its value. A change rolls out to running instances after about 2 minutes without further edits, or at once when you click Roll out now.
| Kind | Description |
|---|---|
| Secret | Reveal shows the last 4 characters. |
| Config | Reveal shows the full value. |
Neither kind appears in a list or in the CLI's output.
synteq function env set KEY=value # secret by default
synteq function env set KEY=value --kind config
synteq function env list
synteq function env reveal KEY
synteq function env rm KEYtakes . (the default) rolls out after the quiet window, replaces running instances right away, starts a new deploy, and leaves the change for your next .
Execution settings
Settings → Execution holds the settings for a running function. Each is bounded by the runtime size, and the ceiling shows beside the field. Defaults and ranges are in Functions overview, under Limits.
| Setting | Description |
|---|---|
| Runtime | The handler's language. Binds at the next deploy. |
| Concurrency | Requests served per instance at once. |
| Timeout | Seconds a run may take before it is killed with . |
| Max instances | How far the function scales out. |
Saving applies the change immediately, without a redeploy. The Activity tab records which settings changed, not the values. How these settings drive dispatch and scaling is in Functions overview, under How functions run.
What next?
- Triggers, operations, and billing: invoke the function, schedule it, and read its logs.
- Functions overview: scaling, cold starts, metering, and limits.
- CLI reference: every flag.