Our @trigger.dev/supabase package provides an integration that wraps the @supabase/supabase-js package, allowing you to run tasks to interact with your Supabase project.

If you want to trigger jobs based on changes in your Supabase database, you’ll need to use the Supabase Management API integration

Usage

Our Supabase integration currently only supports service_role keys:

import { Supabase } from "@trigger.dev/supabase";

const supabase = new Supabase({
  id: "supabase",
  supabaseUrl: `https://<your project id>.supabase.co`,
  supabaseKey: process.env.SUPABASE_SERVICE_ROLE_KEY!,
});

Never expose the service_role key in a browser or anywhere where a user can see it.

You can then use the supabase integration to run tasks in your jobs:

client.defineJob({
  // ...
  integrations: {
    supabase,
  },
  run: async (payload, io, ctx) => {
    const { data: todos, error } = await io.supabase.runTask("find-todos", async (db) => {
      return db.from("todos").select("*");
    });
  },
});

By using runTask instead of the @supabase/supabase-js client directly inside your job run, you’ll be able to create tasks that can be run idempotently and also retried. For more, see our guide on Resumability

You can also choose to throw an error if the query fails and abort the job run:

client.defineJob({
  // ...
  integrations: {
    supabase,
  },
  run: async (payload, io, ctx) => {
    const todos = await io.supabase.runTask("find-todos", async (db) => {
      const { data, error } = await db.from("todos").select("*");

      if (error) throw error;

      return data;
    });
  },
});

The db object passed to the callback is an instance of the @supabase/supabase-js client, so you can use it to run any of the queries or other operations that the client supports:

Currently we do not support Supabase Realtime (such as subscribing to a channel)

Typescript Support

If you have generated types for your Supabase database, you can use them to get type safety for interaction with your database:

import { Supabase } from "@trigger.dev/supabase";
import { Database } from "./supabase.types"; // generated types

const supabase = new Supabase<Database>({
  id: "supabase",
  supabaseUrl: `https://<your project id>.supabase.co`,
  supabaseKey: process.env.SUPABASE_SERVICE_ROLE_KEY!,
});

client.defineJob({
  // ...
  integrations: {
    supabase,
  },
  run: async (payload, io, ctx) => {
    const todos = await io.supabase.runTask("find-todos", async (db) => {
      const { data, error } = await db.from("todos").select("*");

      if (error) throw error;

      return data;
    });

    // todos is now typed as Todo[] instead of any[]
  },
});

For more about generating types, see the Supabase guide