TechLead
Lesson 7 of 8
5 min read
Supabase

Edge Functions

Write serverless functions with Deno that run close to your users

Supabase Edge Functions

Edge Functions are serverless functions written in TypeScript that run on Deno. They execute close to your users for low latency and can access your Supabase project's database, storage, and auth.

⚑ Edge Functions Features

  • Deno Runtime: Modern, secure TypeScript runtime
  • Global Edge: Deploy to 30+ regions worldwide
  • Supabase Integration: Built-in access to your project
  • Webhooks: Handle external service callbacks

Creating an Edge Function

Install Supabase CLI

# Install CLI
npm install -g supabase

# Login to Supabase
supabase login

# Initialize project (if not already)
supabase init

Create a Function

# Create new function
supabase functions new hello-world

This creates supabase/functions/hello-world/index.ts:

import { serve } from "https://deno.land/std@0.168.0/http/server.ts"

serve(async (req) => {
  const { name } = await req.json()

  const data = {
    message: `Hello ${name}!`,
  }

  return new Response(JSON.stringify(data), {
    headers: { "Content-Type": "application/json" },
  })
})

Using Supabase Client

import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
import { createClient } from "https://esm.sh/@supabase/supabase-js@2"

serve(async (req) => {
  // Create Supabase client with service role
  const supabase = createClient(
    Deno.env.get('SUPABASE_URL') ?? '',
    Deno.env.get('SUPABASE_SERVICE_ROLE_KEY') ?? ''
  )

  // Query database
  const { data, error } = await supabase
    .from('posts')
    .select('*')
    .limit(10)

  return new Response(JSON.stringify({ data, error }), {
    headers: { "Content-Type": "application/json" },
  })
})

Handling Auth

import { serve } from "https://deno.land/std@0.168.0/http/server.ts"
import { createClient } from "https://esm.sh/@supabase/supabase-js@2"

serve(async (req) => {
  // Get auth header
  const authHeader = req.headers.get('Authorization')!

  // Create client with user's JWT
  const supabase = createClient(
    Deno.env.get('SUPABASE_URL') ?? '',
    Deno.env.get('SUPABASE_ANON_KEY') ?? '',
    { global: { headers: { Authorization: authHeader } } }
  )

  // Get the user
  const { data: { user }, error } = await supabase.auth.getUser()

  if (error || !user) {
    return new Response('Unauthorized', { status: 401 })
  }

  return new Response(JSON.stringify({ user }), {
    headers: { "Content-Type": "application/json" },
  })
})

Local Development

# Start local Supabase
supabase start

# Serve functions locally
supabase functions serve hello-world --env-file .env.local

Deploying

# Deploy a single function
supabase functions deploy hello-world

# Deploy all functions
supabase functions deploy

Invoking Functions

// From client code
const { data, error } = await supabase.functions.invoke('hello-world', {
  body: { name: 'John' }
})

// With auth (automatically includes user's JWT)
const { data, error } = await supabase.functions.invoke('protected-function', {
  body: { data: 'secure' }
})

CORS Handling

const corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': 'authorization, content-type',
}

serve(async (req) => {
  // Handle CORS preflight
  if (req.method === 'OPTIONS') {
    return new Response('ok', { headers: corsHeaders })
  }

  // Your function logic
  const data = { message: 'Hello!' }

  return new Response(JSON.stringify(data), {
    headers: { ...corsHeaders, 'Content-Type': 'application/json' },
  })
})

πŸ’‘ Key Takeaways

  • β€’ Edge Functions run on Deno with TypeScript support
  • β€’ Use service role key for admin operations
  • β€’ Pass user JWT for authenticated requests
  • β€’ Deploy globally for low latency

πŸ“š Learn More

Continue Learning