> ## Documentation Index
> Fetch the complete documentation index at: https://sequinstream.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Trigger Supabase edge functions from database changes

> Create real-time serverless applications with Postgres change data capture (CDC) and Supabase edge functions.

[Supabase Edge Functions](https://supabase.com/docs/guides/functions) are serverless functions that run on Supabase's global edge network.

Often, you want to trigger a Supabase Edge Function when a database row changes. For example, you may want to trigger a function as a side-effect of a database change, or fan out work to multiple services.

In this guide, you will learn how to setup a Sequin webhook sink to trigger a Supabase Edge Function when a database row changes. This is an alternative to triggering Supabase Edge Functions with Supabase webhooks - and offers additional features like retries and filtering built in.

## Prerequisites

You are about to create a simple Supabase Edge Function that logs a message to the console. You'll trigger this function by setting up a webhook sink in Sequin that sends a HTTP POST request to the function's URL with the payload of the database row that changed.

You'll need the following:

* A [Supabase account](https://supabase.com)
* Sequin [installed locally](/quickstart/webhooks)
* A [Supabase database](/how-to/setup-supabase) connected to Sequin

## Create a Supabase Edge Function

<Steps titleSize="h3">
  <Step title="Create a new edge function">
    Using the [Supabase CLI](https://supabase.com/docs/guides/cli), create a new edge function:

    ```bash theme={null}
    supabase functions new webhook-handler
    ```

    This will create a new TypeScript function in the `supabase/functions/webhook-handler` directory.
  </Step>

  <Step title="Add code to process webhook requests">
    Replace the contents of `supabase/functions/webhook-handler/index.ts` with:

    ```typescript theme={null}
    import { serve } from "https://deno.land/std@0.168.0/http/server.ts"

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

        // Process each change in the batch
        for (const change of data) {
          // Log the database change
          console.log('Database change:', {
            action: change.action,
            table: change.metadata.table_name,
            schema: change.metadata.table_schema,
            record: change.record,
            changes: change.changes,
            timestamp: change.metadata.commit_timestamp,
            consumer: change.metadata.consumer
          })

          // Add your business logic here
          // For example, you could:
          // - Send notifications
          // - Update other services
          // - Transform data
        }

        return new Response(
          JSON.stringify({ message: 'Webhook processed successfully' }),
          {
            status: 200,
            headers: { 'Content-Type': 'application/json' }
          }
        )

      } catch (error) {
        console.error('Error processing webhook:', error)
        return new Response(
          JSON.stringify({ error: 'Error processing webhook' }),
          {
            status: 400,
            headers: { 'Content-Type': 'application/json' }
          }
        )
      }
    })
    ```

    This function will:

    1. Parse the incoming webhook payload from Sequin
    2. Log the database change details
    3. Allow you to add custom business logic if you'd like
    4. Return a success/error response
  </Step>

  <Step title="Test the function locally">
    Start the function locally using the Supabase CLI:

    ```bash theme={null}
    supabase start
    supabase functions serve webhook-handler
    ```

    The function will be available at `http://localhost:54321/functions/v1/webhook-handler`
  </Step>

  <Step title="Deploy the edge function and retrieve the URL">
    Using the Supabase CLI, deploy your edge function:

    ```bash theme={null}
    supabase functions deploy webhook-handler
    ```

    Once deployed, you can retrieve the URL of the edge function by logging into the Supabase Dashboard and navigating to the Edge Functions page. The URL will be in the format:

    ```
    https://<project-ref>.functions.supabase.co/webhook-handler
    ```

    You can also get the URL by running:

    ```bash theme={null}
    supabase functions list
    ```
  </Step>
</Steps>

## Create a Sequin webhook sink

<Steps titleSize="h3">
  <Step title="Create a new sink">
    Navigate to the "Sinks" tab, click the "Create Sink" button, and select "Webhook Sink".
  </Step>

  <Step title="Select source tables">
    Select the schemas and tables you want to capture changes from (i.e `public.users` or `public`).
  </Step>

  <Step title="Add filters (optional)">
    Add [filters](/reference/filters) to the sink to control which database changes are sent to your webhook endpoint.
  </Step>

  <Step title="Configure backfill">
    Leave "Backfill" toggled off for now.
  </Step>

  <Step title="Configure message grouping">
    Under "Message grouping", leave the default option selected to ensure events for the same row are sent to your webhook endpoint in order.
  </Step>

  <Step title="Configure sink settings">
    Under "Webhook Sink configuration" leave the defaults:

    * Leave the default value of `30000 ms` for "Request timeout" as this is more than enough time for your function to process the request
    * Leave the default value of `1` for "Batch size" for now to ensure each change is processed individually.
  </Step>

  <Step title="Configure HTTP endpoint">
    Add your Supabase edge function URL and add an `Authorization` header with the value `Bearer YOUR_SUPABASE_ANON_KEY`.

    <Note>
      The `Authorization` header is required to authenticate the request with the edge function. You can find your `SUPABASE_ANON_KEY` in the "Settings" > "API" page in the Supabase Dashboard. If you don't want to authenticate your request (i.e. make the edge function public), you can deploy the edge function with the `--no-verify-jwt` flag.
    </Note>
  </Step>

  <Step title="Name and create sink">
    Give your sink a name and click "Create Webhook Sink".
  </Step>
</Steps>

## Test end-to-end

<Steps titleSize="h3">
  <Step title="Add a row to your table">
    Insert a row into your table. For example:

    ```sql theme={null}
    insert into
    users (name)
    values
      (
        'John Doe'
      );
    ```
  </Step>

  <Step title="Trace the change in the Sequin dashboard">
    In the Sequin console, open the "Messages" tab on your webhook sink and confirm that a message was delivered.
  </Step>

  <Step title="Confirm the event was received by your edge function">
    In the Supabase Dashboard, navigate to "Edge Functions" and click on your function. You should see the event logged in the function logs.
  </Step>
</Steps>

<Check>
  You've successfully triggered a Supabase Edge Function from a database change!
</Check>

## Next steps

From here, you may want to:

* Refine your webhook sink by using more specific filters. Perhaps you can move logic out of your edge function and into your consumer filters.
* Use Sequin's replay and backfill features to run historical data through your edge function.
* Use Sequin's observability features to monitor and debug your webhooks and triggers.
