# Supabase

Supabase is a backend-as-a-service and framework built around Postgres. It automatically generates a backend API based on the Postgres schema which can be connected to from the frontend. To migrate to Specific, a backend service must be built to replicate the API that Supabase generates automatically, and also implement any edge functions.

Pick a backend stack together with the user (programming language/framework) to be used to replace Supabase.

## Database

Both Supabase and Specific use Postgres, so the schema transfers directly. Determine the schema from the Supabase codebase or export the existing schema from Supabase:

```
supabase db dump --schema public > schema.sql
```

Configure a [Postgres](/postgres) database through Specific connected to the backend and set up the schema and database migrations in the stack chosen for the project.

## API / Backend Service / Edge Functions

Supabase auto-generates a PostgREST API from your database schema. With Specific, you write an explicit backend service that handles routing, request validation, and business logic. This gives you full control over your API surface and means we need to re-implement the routes that Supabase provides derived from the database.

Read the frontend code to determine what endpoints are needed and implement them on the backend. Keep in mind that Supabase uses RLS for authorization, which doesn't translate well without Supabase Authentication present. Instead, read the RLS policies and mirror the logic into the new backend service instead.

Supabase supports writing custom code for the backend using what they call Edge Functions. Transfer these over to be part of the new backend service instead and deployed with the rest of the API.

## Authentication

Supabase Auth (GoTrue) has no direct equivalent in Specific. Instead, authentication should be integrated in whatever way suits the stack chosen for the project, for example:

- Authentication library. For Typescript/Javascript stacks, we recommend [BetterAuth](https://www.better-auth.com/llms.txt)
- External auth provider (Auth0, Clerk, WorkOS, etc.)

Store user data in the same Postgres database your service already connects to. Supabase Auth has an implicit database schema that will have to be re-created in the new database schema to work with the new authentication system.

## Authorization and RLS

Replace the usage of RLS (row level security) in Supabase with authorization and access instead enforced by the new backend code.

## Storage

Supabase Storage is S3-compatible and maps to the object storage available in Specific. See [Storage](/storage) for how to configure this.

## Realtime

Supabase Realtime can be replace with the sync engine available in Specific. See [sync](/sync) for configuration and implementation details.

## Queues

Replace Supabase Queues with a [Temporal](/temporal) workflow engine in Specific. Define a `temporal` block in `specific.hcl` and run a worker service that processes queued work as Temporal workflows or signals. Temporal gives you durable execution, retries, and visibility into queued items via the Temporal Web UI in the admin sidebar.

## Cron

Replace Supabase Cron (pg_cron) with [Temporal Schedules](https://docs.temporal.io/schedules) running on a [Temporal](/temporal) workflow engine in Specific. Define a `temporal` block in `specific.hcl` and have your worker register schedules that trigger workflows at the desired cadence.

## Vector embeddings (pgvector)

If the Supabase project uses `pgvector` for AI embeddings or semantic search, the same extension is available on the Neon-backed [Postgres](/postgres) in Specific. Enable it in a migration with `CREATE EXTENSION IF NOT EXISTS vector;` and the existing schema and queries transfer over unchanged.

## Database functions and triggers

Supabase projects often define SQL functions and triggers, sometimes invoked from the frontend via PostgREST RPC. The functions and triggers themselves transfer directly since they are standard Postgres. However, calls made from the frontend through PostgREST RPC must be re-implemented as explicit endpoints on the new backend service — the backend then invokes the function over the normal Postgres connection.

## Client-side Changes

- Remove the `@supabase/supabase-js` dependency
- Replace all Supabase client calls with standard `fetch` requests to your backend API service
- Pass auth tokens via request headers (e.g., `Authorization: Bearer <token>`) to the backend service for authenticated endpoints

## Migrating existing secrets

If the project has existing secrets in `.env`, `.env.local`, or Supabase configuration files, move them to `specific.local` so they don't need to be re-entered when running `specific dev`:

```hcl
# specific.local
secrets {
  stripe_api_key = "sk_test_..."
  jwt_secret = "..."
}

config {
  api_url = "https://api.example.com"
}
```

Note: Only secrets and configs that are declared in `specific.hcl` need to be added to `specific.local`. The Supabase-specific environment variables (like `SUPABASE_URL` and `SUPABASE_ANON_KEY`) are no longer needed after migration.

## Data migration

Data migration out of Supabase Postgres and Storage (S3) into Specific is currently a manual process. Help guide the user through this if they want it.
