Deploy Edge Functions to branches
Deploy Edge Functions to a DEV branch and merge them to production. POST /v1/projects/functions/deploy accepts multipart/form-data with file (function.zip) and metadata (name, entrypoint_path, import_map_path, static_patterns array, verify_jwt boolean).
Example: Deploy Edge Function
curl https://api.supabase.com/v1/projects/functions/deploy --request POST --header 'Authorization: Bearer YOUR_SECRET_TOKEN' --header 'Content-Type: multipart/form-data' --form 'file=@path/to/function.zip' --form 'metadata={"name": "my-function", "entrypoint_path": "index.ts", "import_map_path": "import_map.json", "static_patterns": ["assets/*", "public/*"], "verify_jwt": true}'
Self-hosted edge function code example
Example Deno function for self-hosted Supabase:
```typescript
Deno.serve(async (req: Request) => {
const { name } = await req.json()
const message = `Hello, ${name}!`
return new Response(JSON.stringify({ message }), {
headers: { 'Content-Type': 'application/json' },
})
})
```
This function reads JSON from the request body, constructs a greeting message, and returns it as JSON.
Self-hosted Edge Functions default setup
Edge Functions work out of the box in a self-hosted Supabase setup. The functions service, API gateway routing, and a hello example function are all pre-configured in the Docker setup.
Invoke default hello function
The default hello function is located at volumes/functions/hello/index.ts and can be invoked immediately after starting the stack using: curl http://<your-domain>/functions/v1/hello. This returns the string "Hello from Edge Functions!".
Create new self-hosted edge function
To create a new function, create a directory at volumes/functions/my-function with an index.ts file containing the function code. After adding the code, restart the functions service with: sh run.sh restart functions. Then invoke it at: curl -X POST http://<your-domain>/functions/v1/my-function with appropriate headers and payload.
Configure edge function environment variables via env file
Create a separate env file (e.g., .env.functions) in the docker/ directory with custom variables. Add env_file to the functions service in docker-compose.yml. Variables in env_file load first, then environment values take precedence. Don't commit .env.functions to version control if it contains secrets; add it to .gitignore. Restart the service with: sh run.sh recreate functions.
Configure edge function environment variables inline
For one or two variables, add them directly under environment in docker-compose.yml: functions: environment: MY_CUSTOM_VAR: ${MY_CUSTOM_VAR}. Then define MY_CUSTOM_VAR in the main .env file or specify the value directly.
Access environment variables in edge functions
All container environment variables are forwarded to function workers by main/index.ts. Access them in functions using: const customVar = Deno.env.get('MY_CUSTOM_VAR')
Pre-configured environment variables for self-hosted functions
The functions service is pre-configured with these environment variables:
| Variable | Value | Purpose |
|----------|-------|----------|
| SUPABASE_URL | http://api-gw:8000 | Internal API gateway URL |
| SUPABASE_PUBLIC_URL | http(s)://<your-domain> | Base URL for accessing Supabase from the Internet |
| JWT_SECRET | your-jwt-secret | Legacy symmetric encryption key for JWTs |
| SUPABASE_ANON_KEY | your-anon-key | Client-side API key (anon role) |
| SUPABASE_SERVICE_ROLE_KEY | your-service-role-key | Server-side API key (service_role role) |
| SUPABASE_DB_URL | postgresql://... | Postgres connection string |
| SUPABASE_PUBLISHABLE_KEYS | {"default":"sb_publishable_...} | New publishable API key |
| SUPABASE_SECRET_KEYS | {"default":"sb_secret_...} | New secret API key |
| SUPABASE_JWKS | {"keys":[{...}]} | JWKS used to verify JWTs issued by Auth |
Call Supabase services from self-hosted edge functions
Example function using @supabase/supabase-js to query a table:
```typescript
import { createClient } from 'https://esm.sh/@supabase/supabase-js@2'
Deno.serve(async () => {
const supabase = createClient(
Deno.env.get('SUPABASE_URL')!,
Deno.env.get('SUPABASE_SERVICE_ROLE_KEY')!
)
const { data, error } = await supabase.from('todos').select('*')
return new Response(JSON.stringify({ data, error }), {
headers: { 'Content-Type': 'application/json' },
})
})
```
Use SUPABASE_URL (internal Docker network hostname) for server-side calls from functions to other Supabase services.
SUPABASE_URL vs SUPABASE_PUBLIC_URL in functions
SUPABASE_URL contains an internal Docker network hostname and should be used for server-side calls from functions to other Supabase services (Auth, Storage, database via PostgREST). This is what the Supabase JS client should use inside functions. SUPABASE_PUBLIC_URL is the externally-reachable URL of your Supabase instance and should be used if your function needs to build URLs that HTTP clients can reach from the outside.
Manage self-hosted functions via dashboard
Self-hosted Studio mounts the same volumes/functions directory as the functions service. You can check what functions are available using Edge Functions > Functions UI in the dashboard.
Deploy edge function to remote self-hosted server
Use scp to copy the function directory to the remote server: scp -r ./my-function user@<your-domain>:/path/to/self-hosted/volumes/functions/. Then restart the functions service on the remote host: ssh user@<your-domain> 'cd /path/to/self-hosted && sh run.sh restart functions'
Copy functions from Supabase platform to self-hosted
Download existing functions from Supabase platform via Dashboard (click Download on function details) or CLI (run supabase functions download <function-name> --project-ref <ref>). Use scp to copy the function into volumes/functions/<function-name>/ on the self-hosted instance, then restart the functions service.
Edge function URL format requirement
The request URL must include the function name after /functions/v1/. For example, /functions/v1/hello. Requests to /functions/v1/ without a function name will return 400 "missing function name in request".
Debug 500 error on edge function invocation
Check the functions service logs using: docker compose logs functions. Common causes of 500 errors include syntax errors in function code, invalid imports, or missing dependencies.
Fix 401 invalid JWT error in edge functions
Check that FUNCTIONS_VERIFY_JWT matches your intent (true or false) in .env. If verification is enabled, ensure you're passing a valid token in the Authorization header: Authorization: Bearer <anon_key or service_role_key>
Reload edge function code changes
If changes to function code are not reflected after editing, restart the functions service: sh run.sh restart functions
Troubleshoot custom environment variables not available in functions
Verify the variable is defined in docker-compose.yml (under env_file or environment). Recreate the functions container after changing configuration: sh run.sh recreate functions. Check that the variable name matches exactly (case-sensitive).
Self-hosted edge function memory and timeout limits
The default limits are 150 MB memory and 60 seconds timeout per function invocation. These are set in volumes/functions/main/index.ts using memoryLimitMb and workerTimeoutMs values. To adjust them, edit these values and restart the functions service.
Self-hosted Edge Functions setup differs from managed platform
On the managed Supabase platform, Edge Functions are deployed across multiple regions. A self-hosted standalone instance configuration resembles a standard serverless setup with functions running on a single instance.
Accessing Edge Functions in self-hosted Supabase
Edge Functions live in volumes/functions. The default setup includes a 'hello' function. Invoke with curl http://<your-domain>:8000/functions/v1/hello. Add new functions at volumes/functions/<FUNCTION_NAME>/index.ts, then restart with sh run.sh restart functions.
Restarting Edge Functions container in self-hosted Supabase
Use sh run.sh restart functions to pick up new or changed function code. Use sh run.sh recreate functions when you change environment variables or secrets (e.g. .env.functions or service's environment: block), since those are only applied when the container is recreated.