Skip to content

Edge functions

Edge functions (PandaEdge) run small units of code on demand, invoked over HTTP. A function is your code (uploaded as a zip) plus a little metadata — timeout, memory, environment variables, and a runtime. Each function gets a stable, name-based invoke URL and keeps a full invocation history you can inspect from the dashboard, CLI, or API.

  • Your code lives in Google Cloud Storage, not in the database. Each upload is stored at {organizationId}/{name}/{version}/{name}.zip. The database holds only metadata and the per-version pointer.
  • Every function runs inside your organization’s namespace, org-{organizationId}.
  • Invocations execute on the PandaStack microVM runtime (the pandastack.ai fn-invoker service), which captures each run’s status, duration, stdout, and stderr.
  • Functions are versioned. Uploading new code creates a new version; metadata-only edits do not. You can roll back to any previous version without re-uploading.

Two runtimes are supported. The runtime determines the entrypoint file PandaStack looks for inside your zip.

Runtimeruntime valueEntrypoint fileNotes
Node.jsnodejsindex.jsDefault runtime.
Pythonpythonmain.py

The entrypoint is auto-detected from the runtime — you do not configure a start command. Package your handler as index.js (Node.js) or main.py (Python) at the root of the zip and PandaStack finds it automatically.

FieldTypeDefaultRangeNotes
namestring1–63 chars, RFC-1123 labelLowercase letters, numbers, hyphens. See naming below.
runtimeenumnodejsnodejs | pythonChooses the entrypoint file.
timeoutnumber (ms)600001000900000Hard cap of 15 minutes.
memorynumber (MB)2561282048Informational / template-baked.
descriptionstring≤ 500 charsOptional.
envarray[][{ "name", "value" }]. Stored as a {KEY:value} object, surfaced back as a list.

The name you choose must be a valid RFC-1123 label (regex ^[a-z0-9]([-a-z0-9]*[a-z0-9])?$). On create, PandaStack appends a random 6-character suffix to guarantee global uniqueness — for example, demo becomes demo-a1b2c3. That suffixed name is what becomes the invoke-URL slug and the GCS path segment, so the public endpoint is stable for the life of the function.

Functions are always addressed by name, never by numeric id, in the invoke path. The public invoke endpoint is:

POST /v1/functions/:name/invoke

Terminal window
# Invoke a function by name (e.g. demo-a1b2c3)
curl -X POST https://api.pandastack.io/v1/functions/demo-a1b2c3/invoke \
-H "Authorization: Bearer $PANDASTACK_TOKEN" \
-H "Content-Type: application/json" \
-d '{ "params": { "hello": "world" } }'

The request body is { "params": <object> } (defaults to {}). The response reports the run outcome:

{
"success": true,
"data": {
"status": "success",
"result": { "ok": true },
"error": null,
"durationMs": 42,
"version": 3
}
}

status is success or error. On failure, result is null and error carries the message; status is error.

For the full request/response schemas of every function endpoint (create, list, versions, rollback, invocation history, metrics), see the Functions API reference.

ActionCreates a version?Effect
Upload new codeYesIncrements currentVersion and adds a version row.
Edit timeout / memory / description / envNoMetadata-only update; version unchanged.
RollbackNoRe-points currentVersion to an existing version. No re-upload needed.

Each version row records its version number and whether it is current. Rolling back is instant because the code for older versions already lives in GCS.

Environment variables are stored as a {KEY: value} object and surfaced in API responses as a list of { name, value } pairs. Editing env is a metadata-only update — it does not create a new version. Your function reads these variables from its process environment at invocation time.

Each organization has a single edge-function API token used internally by the invoker. This token is only ever returned masked in API responses — the clear value is never exposed.

Every invocation is recorded with its status (success | error), duration (ms), stdout, stderr, and timestamp. You can page through this history and read time-bucketed metrics.

Function metrics are computed over the invocation log in 5-minute buckets across the requested window (default: the last 24 hours). They are pure Postgres aggregations — no external time-series store is involved. Each bucket reports:

FieldMeaning
timestampsISO bucket start times.
invocationsInvocation count per bucket.
errorsError count per bucket.
latencyAverage duration (ms) per bucket; null where there were no invocations.