Deploy a Function
Ship a TypeScript function to Amba's edge runtime with `amba functions deploy` — versioned bundles, optional per-function rate limits, and rollback from the console.
amba functions deploy <file> bundles your handler and ships it to your
project's edge runtime. Each deploy is its own version; rollouts are
gradual with auto-rollback on a 5xx breach.
First deploy
Hit it:
Deploying a directory
<target> can be a single file or a directory. A directory is bundled
from its entry — resolved by convention (index.ts / index.js / index.mjs)
or named explicitly with --entry:
This lets a function split across multiple local modules — the bundler follows the imports from the entry. The default name is the directory leaf name.
Flags
--name <name>— function name (default: the file name without extension, or the directory leaf name). The function is served athttps://<project>.fn.amba.host/<name>.--entry <file>— entry file when the target is a directory (relative to it). Default:index.ts/js/mjs.--dry-run— bundle and report size without uploading. Useful for CI to fail when a function approaches the size cap.--rate-limit-window <60s|5m|1h>— per-function rate-limit window.--rate-limit-max <int>— max requests per window.--rate-limit-key <user_id|ip>— bucket key for the rate limit (user_idreads the signed-in user from the session token;ipbuckets by client IP).
All three rate-limit flags must be set together, or all omitted (no rate limit). The edge runtime enforces the limit pre-dispatch — the handler never runs for rate-limited requests.
Rate limit example
That allows each signed-in user 5 requests per minute against
/checkout. The 6th in a window returns 429 Too Many Requests from
the edge without invoking the handler.
Public functions (webhook receivers)
By default every function is private: callers must send your project's
X-Api-Key header, so only your own app reaches it. That's the right
default — keep it for anything only your app calls.
Some callers can't send a custom header. Third-party webhook senders (Stripe, RevenueCat, GitHub, Slack, …) POST to a fixed URL with their own headers and no way to add yours. For those, deploy the function as public so the runtime skips the API-key requirement:
You verify the signature. Public only skips Amba's API-key gate. It does not authenticate the caller for you. A public function is reachable by anyone on the internet, so you must verify the webhook's HMAC signature inside your handler before trusting the payload — exactly as the vendor's docs describe. Public also changes nothing else: your per-function rate limit still applies (set one — public endpoints need it more), and the request still runs inside your own project.
Server-to-server callers (your backend, a cron job, curl, default Python
/ Go HTTP clients) are accepted on function URLs regardless of --public;
they just still need the X-Api-Key header unless the function is public.
Webhook-receiver example
The --public flag is per-function and per-deploy — it travels with the
deployment, so a rollback to a private version restores the API-key
requirement. Deploy without --public to make a function private again.
Reading secrets in production
Secrets set with the CLI are injected as env.* bindings — accessible via
the second parameter to fetch. A secret is project-wide by default
(omit --function, every function sees it) or function-scoped (pass
--function). You can set secrets before this function is deployed; the
sync drains once the deploy lands, and deploy re-syncs at the end.
In local dev, the same key lives in .env.local and is passed to the
handler the same way — see Local dev. For scoping
(project-wide vs. one function) and the full lifecycle, see
Secrets.
Rollback
Every deploy is a new version with a unique id. The console's Rollouts view lists active versions in flight and offers a one-click rollback per version. The CLI also exposes:
If a deploy regresses, ramp the previous version back to 100% from the console Rollouts page.
Watching logs
--tail (alias --follow) streams new log events as they arrive.
--json emits one NDJSON event per line for piping into jq,
log-shipping tools, or local analysis.
When your function throws
If your handler throws an unhandled exception, Amba's edge returns a stable error envelope to the caller and your client SDK will surface it as a typed error. The response shape is:
Key things to know:
-
kind: "function_error"is the SDK-side discriminator. Client SDKs use it to decide not to retry — re-running your code would throw the same exception, so retries would just burn CPU and invocation budget. -
No
retry_afterfield. Absence is the explicit "do not retry" signal. Ifretry_afterIS present on an error, the SDK retries after that many seconds (this is howrate_limited429 andamba_router_unavailable503 work — those are retryable; this is not). -
Status
502, not500. The edge router is a gateway between your caller and your handler; a 502 means "your handler returned an invalid response" (or threw). A 500 would point to a problem on Amba's side — different cause, different fix. -
The exception message is NOT echoed in the response body. Throw messages can carry secrets or PII; the SDK and the caller see only the stable envelope above. Your full stack trace lives in your function's log stream. Pull the log window around the failure and scan for the exception:
To zero in on one request, pass
--request-id— it returns only the events whose logs mention that request id (ther_...value returned to the caller). Works with--tailtoo:
If a caller is seeing function_threw and you didn't expect it, pull
the log window around that time with amba functions logs and find the
exception.
Common pitfalls
- Bundle exceeds size cap —
amba functions deploy --dry-runto see the bundle report. The heaviest deps are usually large NPM packages pulled in transitively; check the report for the top size contributors and prune. - Missing secret at runtime — confirm you ran
amba secrets setfor the project you deployed to.amba secrets listshould show the name (values are never echoed). - First request slow — cold-starts hit after a long idle. The warm-path latency is much lower; in load tests, send a warming request before the burst.
- Caller sees 502
function_threw— your handler threw an unhandled exception. See "When your function throws" above for the full contract. Pull the log window around the error time (amba functions logs <name> --since <iso-timestamp> --json) and match the exception in the output, or pass--request-id <r_...>to filter to that one request's events.
Next
- Local dev — iterate with hot reload before deploy.
- CLI reference — all
amba functionssubcommands.