---
title: "Supabase Client"
sidebarTitle: "JS Client"
description: "Interact with your Supabase project using the Supabase JS Client."
---

Our `@trigger.dev/supabase` package provides an integration that wraps the [@supabase/supabase-js](https://github.com/supabase/supabase-js) package, allowing you to run tasks to interact with your Supabase project.

<Note>
  If you want to trigger jobs based on changes in your Supabase database, you'll need to use the
  [Supabase Management API](/integrations/apis/supabase/management) integration
</Note>

## Usage

Our Supabase integration currently only supports [service_role](https://supabase.com/docs/guides/api/api-keys#the-servicerole-key) keys:

```ts
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!,
});
```

<Warning>
  Never expose the `service_role` key in a browser or anywhere where a user can see it.
</Warning>

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

```ts
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("*");
    });
  },
});
```

<Note>
  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](http://localhost:3050/documentation/concepts/resumability)
</Note>

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

```ts
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](https://github.com/supabase/supabase-js) client, so you can use it to run any of the queries or other operations that the client supports:

- [Databases](https://supabase.com/docs/reference/javascript/select)
- [Auth](https://supabase.com/docs/reference/javascript/auth-signup)
- [Invoking Functions](https://supabase.com/docs/reference/javascript/functions-invoke)
- [Storage](https://supabase.com/docs/reference/javascript/storage-createbucket)

<Warning>Currently we do not support Supabase Realtime (such as subscribing to a channel)</Warning>

## Typescript Support

If you have [generated types](https://supabase.com/docs/reference/javascript/typescript-support) for your Supabase database, you can use them to get type safety for interaction with your database:

```ts
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](https://supabase.com/docs/reference/javascript/typescript-support)
