name: supabase-edge-functions description: Guidelines for writing Supabase Edge Functions with TypeScript and Deno runtime. Use when creating or modifying edge functions in supabase/functions/.
Writing Supabase Edge Functions
Generate high-quality Supabase Edge Functions that adhere to the following best practices.
Guidelines
- Try to use Web APIs and Deno's core APIs instead of external dependencies (eg: use fetch instead of Axios, use WebSockets API instead of node-ws)
- If you are reusing utility methods between Edge Functions, add them to
supabase/functions/_sharedand import using a relative path. Do NOT have cross dependencies between Edge Functions. - Do NOT use bare specifiers when importing dependencies. If you need to use an external dependency, make sure it's prefixed with either
npm:orjsr:. For example,@supabase/supabase-jsshould be written asnpm:@supabase/supabase-js. - For external imports, always define a version. For example,
npm:@expressshould be written asnpm:express@4.18.2. - For external dependencies, importing via
npm:andjsr:is preferred. Minimize the use of imports fromdeno.land/x,esm.shandunpkg.com. If you have a package from one of those CDNs, you can replace the CDN hostname withnpm:specifier. - You can also use Node built-in APIs. You will need to import them using
node:specifier. For example, to import Node process:import process from "node:process". Use Node APIs when you find gaps in Deno APIs. - Do NOT use
import { serve } from "https://deno.land/std@0.168.0/http/server.ts". Instead use the built-inDeno.serve. - Following environment variables (ie. secrets) are pre-populated in both local and hosted Supabase environments. Users don't need to manually set them:
- SUPABASE_URL
- SUPABASE_ANON_KEY
- SUPABASE_SERVICE_ROLE_KEY
- SUPABASE_DB_URL
- To set other environment variables (ie. secrets) users can put them in a env file and run the
supabase secrets set --env-file path/to/env-file - A single Edge Function can handle multiple routes. It is recommended to use a library like Express or Hono to handle the routes as it's easier for developer to understand and maintain. Each route must be prefixed with
/function-nameso they are routed correctly. - File write operations are ONLY permitted on
/tmpdirectory. You can use either Deno or Node File APIs. - Use
EdgeRuntime.waitUntil(promise)static method to run long-running tasks in the background without blocking response to a request. Do NOT assume it is available in the request / execution context.
Example Templates
Simple Hello World Function
interface reqPayload {
name: string
}
console.info('server started')
Deno.serve(async (req: Request) => {
const { name }: reqPayload = await req.json()
const data = {
message: `Hello ${name} from foo!`,
}
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json', Connection: 'keep-alive' },
})
})
Example Function using Node built-in API
import { randomBytes } from 'node:crypto'
import process from 'node:process'
const generateRandomString = (length) => {
const buffer = randomBytes(length)
return buffer.toString('hex')
}
const randomString = generateRandomString(10)
console.log(randomString)
Deno.serve(async (req: Request) => {
return new Response('Hello', {
headers: { 'Content-Type': 'text/plain' },
})
})
Using npm packages in Functions
import express from 'npm:express@4.18.2'
const app = express()
app.get(/(.*)/, (req, res) => {
res.send('Welcome to Supabase')
})
app.listen(8000)
Generate embeddings using built-in @Supabase.ai API
const model = new Supabase.ai.Session('gte-small')
Deno.serve(async (req: Request) => {
const params = new URL(req.url).searchParams
const input = params.get('text')
const output = await model.run(input, { mean_pool: true, normalize: true })
return new Response(JSON.stringify(output), {
headers: {
'Content-Type': 'application/json',
Connection: 'keep-alive',
},
})
})