Products
Edge Functions
Serverless TypeScript (Deno) functions hosted next to your database — deployed from the dashboard, API or MCP.
Edge Functions are TypeScript functions running in Deno (Supabase Edge Runtime) next to your database. Every function gets a public URL:
https://<ref>.host.ulewicz.space/functions/v1/<name>
Function names use lowercase letters, digits, - and _, and start with a letter (e.g. send-email). The name main is reserved.
Deploying from the dashboard
- Open your project → Edge Functions → New function.
- Pick a template (Hello World, REST API with CORS, database query, webhook → table, Stripe webhook, Resend e-mail, Slack notifications, AI chat with Claude, scheduled job) or start blank. The dashboard shows which secrets a template needs and whether they're set.
- Give it a name and click Create and deploy. The function is live within seconds.
- Edit the code in the Code tab (file tree, syntax highlighting) and deploy with
⌘/Ctrl + S; every deploy bumps the version.
Function tabs
| Tab | What it contains |
|---|---|
| Test | A test request (method, path, headers, body; anon key, service_role or no auth) and the response with status, timing and headers. |
| Analytics | Invocations and 4xx/5xx over time vs. the previous period, latency distribution with p50/p95/p99, status codes, a weekday × hour heatmap and cold starts. |
| Logs | console.log/console.error output attributed to invocations, plus recent HTTP requests. |
| History | Every deployed version, a diff between any two versions and one-click rollback. |
| Schedule | Run the function on a cron schedule — see below. |
| Settings | JWT verification and deleting the function. |
Example function
// index.ts
import { createClient } from "npm:@supabase/supabase-js@2";
Deno.serve(async (req) => {
const { name } = await req.json();
const supabase = createClient(
Deno.env.get("SUPABASE_URL")!,
Deno.env.get("SUPABASE_ANON_KEY")!,
{ global: { headers: { Authorization: req.headers.get("Authorization")! } } }
);
const { data: { user } } = await supabase.auth.getUser();
return Response.json({ message: "Hello " + (name ?? user?.email ?? "stranger") });
});
npm: and jsr: imports work without configuration. A function can have multiple files — the entry point is always index.ts.
Calling from the client
const { data, error } = await supabase.functions.invoke("hello", {
body: { name: "Ann" },
});
JWT verification
By default a function requires an Authorization: Bearer <JWT> header (the anon key or a signed-in user's token) — without it the runtime returns 401 before your code runs. For webhooks (Stripe, GitHub) turn off verify_jwt in the function's settings and verify the signature in code.
Secrets
Set API keys in Edge Functions → Secrets (one by one or by importing a .env file) and read them with Deno.env.get("NAME"). Values live only on the project's server and are never displayed or returned by the API. After changing secrets the runtime restarts (a few seconds).
SUPABASE_URL, SUPABASE_ANON_KEY, SUPABASE_SERVICE_ROLE_KEY and SUPABASE_DB_URL are injected automatically — the SUPABASE_ prefix is reserved.
Deploying via the API
curl -X PUT https://host.ulewicz.space/api/v1/projects/<ref>/functions/hello \
-H "Authorization: Bearer $HOSTBASE_TOKEN" \
-H "Content-Type: application/json" \
-d '{"code":"Deno.serve(() => Response.json({ ok: true }))","verify_jwt":true}'
See the Management API for all endpoints, the CLI (hostbase functions deploy) and the MCP server (deploy_edge_function).
Schedules (cron)
In a function's Schedule tab you can add a recurring invocation (preset or custom cron expression in UTC). The dashboard creates a pg_cron job in your database that calls the function through pg_net; the service_role key is kept in Supabase Vault, not in the job itself.
Limits
| Value | |
|---|---|
| Function code size | 1 MB (all files combined) |
| Worker memory | 150 MB |
| Max response wait | 150 s |
| Cold start | a worker is released after 60 s without requests |
| Version history | last 50 versions per function |