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

# Supabase + PowerSync

> Build offline-first apps with Supabase and PowerSync across Flutter, React Native, Web, Kotlin, and Swift.

<Frame caption="Video walkthrough of the integration guide.">
  <iframe width="1005" height="420" src="https://www.youtube.com/embed/Xg5FTYGPn5U?si=4TjdYEACDR2g98yh" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share; fullscreen" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen />
</Frame>

Used in conjunction with **Supabase**, PowerSync enables developers to build local-first & offline-first apps that are robust in poor network conditions and that have highly responsive frontends while relying on [Supabase](https://supabase.com/) for their backend. This guide provides instructions for how to configure PowerSync for use with your Supabase project.

<Warning>
  Note: We are currently investigating an issue with Supabase logical replication where unused/idle instances have excessive WAL growth, resulting in maxed out disk usage. Supabase seem to have updated the default archive\_timeout setting to 2 min, which seems to be part of the issue. The current recommendation for pet/hobby projects is to set a smaller `max_wal_size` and `max_slot_wal_keep_size`:

  ```bash theme={null}
  supabase --experimental \
    --project-ref <project-ref> \
    postgres-config update --config max_wal_size=1GB
  ```

  and also:

  ```bash theme={null}
  supabase --experimental \
    --project-ref <project-ref> \
    postgres-config update --config max_slot_wal_keep_size=1GB
  ```
</Warning>

<Note>
  Before you proceed, this guide assumes that you have already signed up for free accounts with both Supabase and PowerSync Cloud (our cloud-hosted offering). If you haven't signed up for a **PowerSync** (Cloud) account yet, [click here](https://accounts.powersync.com/portal/powersync-signup?s=docs) (and if you haven't signed up for Supabase yet, [click here](https://supabase.com/dashboard/sign-up)).
</Note>

<Note>
  For mobile/desktop apps, this guide assumes that you already have **Flutter / React Native / Kotlin / Xcode** set up.

  For web apps, this guide assumes that you have [pnpm](https://pnpm.io/installation#using-npm) installed.
</Note>

<Check>
  This guide takes 10-15 minutes to complete.
</Check>

## Architecture

Upon successful integration of Supabase + PowerSync, your system architecture will look like this: (click to enlarge image)

<Frame>
  <img src="https://mintcdn.com/powersync/WHAzIyIUEG5c_Y5t/images/integration-guides/supabase/powersync-docs-diagram-supabase-integration.png?fit=max&auto=format&n=WHAzIyIUEG5c_Y5t&q=85&s=13b17029fa3ec4566aa14c6aab821a76" width="1920" height="1080" data-path="images/integration-guides/supabase/powersync-docs-diagram-supabase-integration.png" />
</Frame>

The local SQLite database embedded in the PowerSync SDK is automatically kept in sync with the Supabase Postgres database (based on your Sync Streams as you will see later in this guide). Client-side data modifications are persisted in the local SQLite database as well as stored in an upload queue that gets processed via the Supabase client library when network connectivity is available. Therefore reads and writes can happen in the app regardless of whether the user is online or offline, by using the local SQLite database.

<Note>
  For more details on PowerSync's general architecture, [see here](/architecture/architecture-overview).
</Note>

## Integration Guide/Tutorial Overview

We will follow these steps to get an offline-first 'To-Do List' demo app up and running:

<Steps>
  <Step title="Configure Supabase:">
    * Create the demo database schema
    * Create the Postgres user and publication
  </Step>

  <Step title="Configure PowerSync:">
    * Create connection to Supabase
    * Configure Sync Streams
  </Step>

  <Step title="Test the configuration">
    Test the configuration using our provided PowerSync-Supabase 'To-Do List' demo app with your framework of choice.
  </Step>
</Steps>

## Configure Supabase

Create a new Supabase project (or use an existing project if you prefer) and follow the below steps.

### Create the Demo Database Schema

To set up the Postgres database for our *To-Do List* demo app, we will create two new tables: `lists` and `todos`. The demo app will have access to these tables even while offline.

Run the below SQL statements in your **Supabase SQL Editor**:

```sql theme={null}
create table
  public.lists (
    id uuid not null default gen_random_uuid (),
    created_at timestamp with time zone not null default now(),
    name text not null,
    owner_id uuid not null,
    constraint lists_pkey primary key (id),
    constraint lists_owner_id_fkey foreign key (owner_id) references auth.users (id) on delete cascade
  ) tablespace pg_default;

create table
  public.todos (
    id uuid not null default gen_random_uuid (),
    created_at timestamp with time zone not null default now(),
    completed_at timestamp with time zone null,
    description text not null,
    completed boolean not null default false,
    created_by uuid null,
    completed_by uuid null,
    list_id uuid not null,
    constraint todos_pkey primary key (id),
    constraint todos_created_by_fkey foreign key (created_by) references auth.users (id) on delete set null,
    constraint todos_completed_by_fkey foreign key (completed_by) references auth.users (id) on delete set null,
    constraint todos_list_id_fkey foreign key (list_id) references lists (id) on delete cascade
  ) tablespace pg_default;
```

### Create a PowerSync Database User

PowerSync uses the Postgres [Write Ahead Log (WAL)](https://www.postgresql.org/docs/current/wal-intro.html) to replicate data changes in order to keep PowerSync SDK clients up to date.

Run the below SQL statement in your **Supabase SQL Editor** to create a Postgres role/user with replication privileges:

```sql theme={null}
-- Create a role/user with replication privileges for PowerSync
CREATE ROLE powersync_role WITH REPLICATION BYPASSRLS LOGIN PASSWORD 'myhighlyrandompassword';
-- Set up permissions for the newly created role
-- Read-only (SELECT) access is required
GRANT SELECT ON ALL TABLES IN SCHEMA public TO powersync_role;  

-- Optionally, grant SELECT on all future tables (to cater for schema additions)
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO powersync_role; 
```

To restrict read access to specific tables, explicitly list allowed tables for both the `SELECT` privilege, and for the publication mentioned in the next step (as well as for any other publications that may exist).

### Create the Postgres Publication

Run the below SQL statement in your **Supabase SQL Editor** to create a Postgres publication:

```sql theme={null}
-- Create a publication to replicate tables. The publication must be named "powersync"
CREATE PUBLICATION powersync FOR ALL TABLES;
```

<Warning>
  Note that the PowerSync Service has to read all updates present in the publication, regardless of whether the table is referenced in your Sync Streams / Sync Rules definitions. This can cause large spikes in memory usage or introduce replication delays, so if you're dealing with large data volumes, you'll want to specify a comma-separated subset of tables to replicate instead of `FOR ALL TABLES`.
</Warning>

<Warning>
  The snippet above replicates all tables and is the simplest way to get started in a dev environment.
</Warning>

## Configure PowerSync

### Create a PowerSync Cloud Instance

When creating a project in the [PowerSync Dashboard](https://dashboard.powersync.com/), *Development* and *Production* instances of the PowerSync Service will be created by default. Select the instance you want to configure.

If you need to create a new instance, follow the steps below.

1. In the dashboard, select your project and open the instance selection dropdown. Click **Add Instance**.

<Frame>
  <img src="https://mintcdn.com/powersync/m6fGEiJuEsLbVG1i/images/usage/tools/dashboard-add-instance.png?fit=max&auto=format&n=m6fGEiJuEsLbVG1i&q=85&s=de9f14ebfe66bd261f3cefbd883ed5c7" width="737" height="167" data-path="images/usage/tools/dashboard-add-instance.png" />
</Frame>

2. Give your instance a name, such as "Production".
3. \[Optional] You can change the default cloud region from US to EU, JP (Japan), AU (Australia) or BR (Brazil) if desired.
   * Note: Additional cloud regions will be considered on request, especially for customers on our Enterprise plan. Please [contact us](/resources/contact-us) if you need a different region.
4. Click **Create Instance**.

### Connect PowerSync to Your Supabase

1. From your Supabase Dashboard, select **Connect** in the top navigation bar (or follow this [link](https://supabase.com/dashboard/project/_?showConnect=true)):

   <Frame>
     <img src="https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/installation/supabase-connect-database.png?fit=max&auto=format&n=lquPOu2QW4XM9BQW&q=85&s=1efc08293ed7ad30b61896250dfda8d8" width="1374" height="398" data-path="images/installation/supabase-connect-database.png" />
   </Frame>

2. In the **Direct connection** section, copy the complete connection string (including the `[YOUR-PASSWORD]` placeholder):

   <Frame>
     <img src="https://mintcdn.com/powersync/lquPOu2QW4XM9BQW/images/installation/supabase-connection-string.png?fit=max&auto=format&n=lquPOu2QW4XM9BQW&q=85&s=32c89e9a442743ad4725d5d666a7c0da" width="1078" height="612" data-path="images/installation/supabase-connection-string.png" />
   </Frame>

3. In the [PowerSync Dashboard](https://dashboard.powersync.com/), select your project and instance and go to **Database Connections**.

4. Click **Connect to Source Database** and ensure the **Postgres** tab is selected.

5. Paste the connection string into the **URI** field. PowerSync will automatically parse this URI to populate the database connection details.

6. Update the **Username** and **Password** fields to use the `powersync_role` and password you created when configuring your Supabase for PowerSync (see [Source Database Setup](/configuration/source-db/setup#supabase)).

7. Note: PowerSync includes Supabase's CA certificate by default, so you can use `verify-full` SSL mode without additional configuration.

<Frame caption="Your Supabase connection details should look similar to this.">
  <img src="https://mintcdn.com/powersync/4UHxJMSnMXF9MPuh/images/installation/dashboard-supabase-connection.png?fit=max&auto=format&n=4UHxJMSnMXF9MPuh&q=85&s=72c922931abb5c94503f012b0c77ac0a" width="2139" height="928" data-path="images/installation/dashboard-supabase-connection.png" />
</Frame>

7. Verify your setup by clicking **Test Connection** and resolve any errors.
8. Click **Save Connection**.

PowerSync will now create an isolated cloud environment for your instance. This typically takes a minute or two.

### Enable Supabase Auth

After your database connection is configured, enable Supabase Auth:

1. In the PowerSync Dashboard, go to **Client Auth** for your instance.
2. Enable the **Use Supabase Auth** checkbox.
3. If your Supabase project uses the legacy JWT signing keys, copy your JWT Secret from your Supabase project's settings ([JWT Keys](https://supabase.com/dashboard/project/_/settings/jwt)) and paste the secret into the **Supabase JWT Secret (optional) Legacy** field in the PowerSync Dashboard. If you're using Supabase's new [JWT signing keys](https://supabase.com/blog/jwt-signing-keys), you can leave this field empty (PowerSync will auto-configure the JWKS endpoint for your project).
4. Click **Save and Deploy** to apply the changes.

### Configure Sync Streams

[Sync Streams](/sync/streams/overview) (or legacy [Sync Rules](/sync/rules/overview)) allow developers to control which data gets synced to which user devices using a SQL-like syntax in a YAML file. For the demo app, we're going to specify that each user can only see their own to-do lists and list items.

1. In the [PowerSync Dashboard](https://dashboard.powersync.com/), select your project and instance and go to the **Sync Streams** view (shown as **Sync Rules** if using legacy Sync Rules).

2. Edit the Sync Streams in the editor and replace the contents with the below:

<Tabs>
  <Tab title="Sync Streams (Recommended)">
    ```yaml theme={null}
    config:
      edition: 3
    streams:
      user_data:
        auto_subscribe: true
        queries:
        - SELECT * FROM lists WHERE owner_id = auth.user_id()
        - SELECT todos.* FROM todos INNER JOIN lists ON todos.list_id = lists.id WHERE lists.owner_id = auth.user_id()
        
    ```
  </Tab>

  <Tab title="Sync Rules (Legacy)">
    ```yaml theme={null}
    bucket_definitions:
      user_lists:
        # Separate bucket per To-Do list
        parameters: select id as list_id from lists where owner_id = request.user_id()
        data:
          - select * from lists where id = bucket.list_id
          - select * from todos where list_id = bucket.list_id
    ```
  </Tab>
</Tabs>

2. Click **"Validate"** and ensure there are no errors. This validates your sync config against your Postgres database.
3. Click **"Deploy"** to deploy your sync config.

<Tip>
  * For additional information on PowerSync's Sync Streams, refer to the [Sync Streams](/sync/streams/overview) documentation.
  * For legacy Sync Rules, refer to the [Sync Rules](/sync/rules/overview) documentation.
  * If you're wondering how Sync Streams relate to Supabase Postgres [RLS](https://supabase.com/docs/guides/auth/row-level-security), see [this subsection](/integrations/supabase/rls-and-sync-streams).
</Tip>

## Test Everything (Using Our Demo App)

In this step you'll test your setup using a 'To-Do List' demo app provided by PowerSync.

#### Clone the Demo App

Clone the demo app based on your framework:

<CodeGroup>
  ```bash Flutter theme={null}
  git clone https://github.com/powersync-ja/powersync.dart.git
  cd powersync.dart/demos/supabase-todolist/
  ```

  ```bash React Native theme={null}
  git clone https://github.com/powersync-ja/powersync-js.git
  cd powersync-js/demos/react-native-supabase-todolist
  ```

  ```bash JavaScript Web theme={null}
  git clone https://github.com/powersync-ja/powersync-js.git
  cd powersync-js/demos/react-supabase-todolist
  ```

  ```bash Kotlin theme={null}
  git clone https://github.com/powersync-ja/powersync-kotlin.git

  # Open `demos/supabase-todolist` in Android Studio
  ```

  ```bash Swift theme={null}
  git clone https://github.com/powersync-ja/powersync-swift.git

  # Open the Demo directory in XCode and follow the README instructions.
  ```
</CodeGroup>

#### Configure the Demo App to Use Your PowerSync Instance

Locate the relevant config file for your framework:

<CodeGroup>
  ```bash Flutter theme={null}
  cp lib/app_config_template.dart lib/app_config.dart

  # Edit `lib/app_config.dart` and insert the necessary credentials as detailed below.
  ```

  ```bash React Native theme={null}
  # Edit the `.env` file and insert the necessary credentials as detailed below.
  ```

  ```bash JavaScript Web theme={null}
  cp .env.local.template .env.local

  # Edit `.env.local` and insert the necessary credentials as detailed below.
  ```

  ```bash Kotlin theme={null}
  # Make a `local.properties` file in the root and fill in the relevant variables (see points below for further details):

  # local.properties
  sdk.dir=/path/to/android/sdk

  # Enter your PowerSync instance URL
  POWERSYNC_URL=https://foo.powersync.journeyapps.com
  # Enter your Supabase project's URL and public anon key
  SUPABASE_URL=https://foo.supabase.co # from https://supabase.com/dashboard/project/_/settings/api
  SUPABASE_ANON_KEY=foo # from https://supabase.com/dashboard/project/_/settings/api-keys
  ```

  ```bash Swift theme={null}
  # Edit the `_Secrets` file and insert the necessary credentials as detailed below.
  ```
</CodeGroup>

1. In the relevant config file, replace the values for `supabaseUrl` (from the [Project URL](https://supabase.com/dashboard/project/_/settings/api) section in the Supabase dashboard) and `supabaseAnonKey` (from the [API Keys](https://supabase.com/dashboard/project/_/settings/api-keys) section in the Supabase dashboard)
2. For the value of `powersyncUrl`, click **Connect** in the top bar of the [PowerSync Dashboard](https://dashboard.powersync.com/) and copy the instance URL from the dialog.

#### Run the App

<CodeGroup>
  ```bash Flutter theme={null}
  # Ensure you have [melos](https://melos.invertase.dev/~melos-latest/getting-started) installed.

  melos bootstrap
  flutter run
  ```

  ```bash React Native theme={null}
  # In the repo root directory:
  pnpm install
  pnpm build:packages

  # In `demos/react-native-supabase-todolist`:
  # Run on iOS
  pnpm ios
  # Run on Android
  pnpm android
  ```

  ```bash JavaScript Web theme={null}
  # In the repo root directory:
  pnpm install
  pnpm build:packages

  # In `demos/react-supabase-todolist`:
  pnpm dev
  ```

  ```bash Kotlin theme={null}
  # Run the app on Android or iOS in Android Studio using the Run widget.
  ```

  ```bash Swift theme={null}
  # Run the app using XCode.
  ```
</CodeGroup>

<Note>
  For ease of use of the demo app, you can disable email confirmation in your Supabase Auth settings. In your Supabase project, go to "Authentication" -> "Providers" -> "Email" and then disable "Confirm email". If you keep email confirmation enabled, the Supabase user confirmation email will reference the default Supabase Site URL of `http://localhost:3000` — you can ignore this.
</Note>

<img src="https://mintcdn.com/powersync/xadPobk0au2zv_hA/images/integration-8.png?fit=max&auto=format&n=xadPobk0au2zv_hA&q=85&s=46225f465952196e06307d445fab55d0" width="30%" data-path="images/integration-8.png" />

Once signed in to the demo app, you should see a blank list of to-do lists, so go ahead and create a new list. Try placing your device into airplane mode to test out the offline capabilities. Once the device is back online, you should see the data automatically appear in your Supabase dashboard (e.g. in the Table Editor).

For more information, explore the [PowerSync docs](/) or join us on [our community Discord](https://discord.gg/powersync) where our team is always available to answer questions.

## Bonus: Optional Extras

If you plan on sharing this demo app with other people, you may want to set up demo data triggers so that new user signups don't see an empty screen.

It's useful to have some data when a user signs up to the demo app. The below trigger automatically creates some sample data when a user registers (you can run it in the Supabase SQL Editor). See [Supabase: Managing User Data](https://supabase.com/docs/guides/auth/managing-user-data#using-trigger) for more details.

```sql theme={null}
create function public.handle_new_user_sample_data()
returns trigger as $$
declare
  new_list_id uuid;
begin
  insert into public.lists (name, owner_id)
    values ('Shopping list', new.id)
    returning id into new_list_id;

  insert into public.todos(description, list_id, created_by)
    values ('Bread', new_list_id, new.id);

  insert into public.todos(description, list_id, created_by)
    values ('Apples', new_list_id, new.id);

  return new;
end;
$$ language plpgsql security definer;

create trigger new_user_sample_data after insert on auth.users for each row execute procedure public.handle_new_user_sample_data();
```
