Skip to main content
Oxygen Functions are TypeScript handlers that ship inside your SDK app and run server-side on Oxygen’s managed V8 isolate runtime, with direct access to your project’s data plane. Reach for them whenever the browser shouldn’t do the work itself:
  • a parameterized or privileged warehouse query,
  • a warehouse write (insert / upsert / exec),
  • kicking off an Airway ELT run,
  • an outbound API call to a third-party service.
No separate backend to stand up — a function is versioned and deployed with your frontend by oxy publish.
An Oxygen Function is a bundled TypeScript handler — not a YAML Automation task or a Data App task. It runs with the app’s project-level access, not the invoking visitor’s.

Authoring a function

A function is a file at functions/<name>.ts that exports a default async (req, ctx) => Response, declared in the app’s oxy-app.json:
functions/daily-rollup.ts
oxy-app.json
  • req is { body: string } — the raw POST body. Response / Response.json(...) are polyfilled by the runtime.
  • ctx is the data plane:
    • ctx.query / ctx.queryStream — read-only, row-capped SQL
    • ctx.semantic.query — a semantic-model query
    • ctx.warehouse.{insert, exec, upsert} — writes, allowlisted to project databases
    • ctx.airway.run — kick off an ELT pipeline
    • ctx.fetch — outbound HTTP, SSRF-allowlisted, HTTPS-only, size/time-capped
    • ctx.env — per-app secrets
    • ctx.user, ctx.log

Invocation modes

A function can be reached three ways, each with its own identity and default timeout (a ceiling; max 300s): The route endpoint (POST /customer-apps/<org>/<slug>/fn/<name>) is POST-only (405 otherwise), rate-limited per (user, app, function), and every invocation is audited.

Calling a route function from React

Use the useFunction hook to invoke a route function imperatively — e.g. from a button:
  • invoke(body?, { idempotencyKey? }) returns the function’s JSON response.
  • rollup.data holds the last successful result; rollup.error the last error.
  • Concurrent identical invokes are deduplicated into one request.

Caching

Results are not cached by default — functions are often side-effectful. A read-only function can opt into a server result cache by adding "cache": { "ttlSeconds": N } to its manifest entry; the cache is keyed per (build, user, body), invalidated by the next publish, and bypassed with ?refresh.

Next steps

Hooks & components

The rest of the SDK surface

SDK overview

Scaffold, wire up, and deploy an app