This guide explains how to use thesupabase-cli migration tool to migrate a complete Supabase project, including its database, storage objects, and Edge Functions, to AnalyticDB Supabase. This service is powered by AnalyticDB for PostgreSQL.
Use cases
Migration paths
Migrate from Supabase Cloud to AnalyticDB Supabase.
Migrate from a self-hosted Supabase project to AnalyticDB Supabase.
Migrate between AnalyticDB Supabase projects.
Migration scope
Database schema: Includes table structures, functions, and triggers.
Database data: Includes user data, auth data, and other system data.
PostgreSQL extensions: Installs the required plugins in the target project automatically.
Storage objects: Includes buckets and the files within them.
Edge Functions: Includes function code and related configurations.
Roles and permissions: Includes database user and permission settings.
Command syntax
Select the migration tool for your platform and run the following command.
./supabase-cli migrate-project [flags]Required parameters
Source environment configuration
Supabase Cloud source configuration
--source-project-ref string # Source project reference ID (Required) --source-anon-key string # Source project anonymous key (Required) --source-service-role-key string # Source project service role key (Required)A self-hosted Supabase project or an AnalyticDB Supabase instance
--source-api-url string # Source API URL (Required) --source-anon-key string # Source project anonymous key (Required) --source-service-role-key string # Source project service role key (Required) --source-database-url string # Source database URL (Required). Must be percent-encoded.
Target environment configuration
--target-api-url string # Target API URL (Required) --target-anon-key string # Target project anonymous key (Required) --target-service-role-key string # Target project service role key (Required) --target-database-url string # Target database URL (Required). Must be percent-encoded.
Optional parameters
Supabase Cloud source configuration
--source-database-url string # Source database URL (Optional). Must be percent-encoded.Migration content
--include-data # Include database data (default: true) --include-storage # Include storage objects (default: true) --include-functions # Include Edge Functions (default: true) --include-system-data # Include system module data (default: true)Execution options
--use-local-exec # Use a local executor instead of a Docker container. Requires local installation of tools like pg_dump. --concurrency int # Number of concurrent operations (default: 2) --dry-run # Runs in preview mode without performing the migration. --resume-from string # Resume from a specified step (database|storage|functions)Security options
ImportantWhen using the
--allow-truncateparameter, ensure that the source and target configurations are correct to prevent accidental data deletion from the source database.--allow-truncate # Allow clearing table data (default: false) --preserve-extra-tables # Preserve extra tables in the target database (default: true)
Usage notes
Before migrating a production environment, thoroughly test the migration process in a staging environment.
Maintain a stable network connection during the migration.
Migrating a large database can take a long time. Plan your migration window accordingly.
We recommend performing production environment migrations during off-peak hours.
Prerequisites
Ensure the following network connections are stable. For AnalyticDB Supabase-specific operations, see Modify a Whitelist.
You can access the API and database of the source Supabase project.
You can access the API and database of the target environment.
The target database allows external connections.
Docker is installed and running.
Procedure
Step 1: Get project information and set environment variables
Obtain the source configuration information.
For Supabase Cloud, get the following information from your project's settings page.
Project Ref: A 20-character project ID.
Go to the Supabase console.
Click the source project and view the URL. For example, in the URL
https://supabase.com/dashboard/project/qeqfhfoebrtkbmwd****, the Project Ref is at the end (qeqfhfoebrtkbmwd****).
Anon Key: The anonymous key, which starts with
eyJ.Service Role Key: The service role key, which starts with
eyJ. This key must have permission to read all data.Database URL (Optional): The PostgreSQL connection string.
On the source project page, click connect, go to the Connection String tab, and select Transaction pooler as the Method.

Obtain the target AnalyticDB Supabase configuration information. For more details, see Obtain API Keys.
API URL: The full API address, such as
https://your-domain.supabase.opentrust.net.Anon Key: The anonymous key for the target environment.
Service Role Key: The service role key for the target environment. This key must have full administrative permissions.
Database URL: The PostgreSQL connection string. The target database user must have permissions to create tables, plugins, and other objects.
(Optional) To avoid exposing sensitive information on the command line, configure project information as environment variables.
Migrate from Supabase Cloud to AnalyticDB Supabase
# Create a configuration file cat > migration.env << 'EOF' SOURCE_PROJECT_REF="your-project-ref" SOURCE_ANON_KEY="eyJ..." SOURCE_SERVICE_ROLE_KEY="eyJ..." TARGET_API_URL="https://your-domain.supabase.opentrust.net" TARGET_ANON_KEY="eyJ..." TARGET_SERVICE_ROLE_KEY="eyJ..." TARGET_DATABASE_URL="postgres://postgres:password@{your-project-id}.supabase.opentrust.net:5432/postgres" EOF # Load the environment variables source migration.envMigrate from a self-hosted Supabase or AnalyticDB Supabase to AnalyticDB Supabase
# Create a configuration file cat > migration.env << 'EOF' SOURCE_API_URL="http://localhost:54321" SOURCE_ANON_KEY="eyJ..." SOURCE_SERVICE_ROLE_KEY="eyJ..." SOURCE_DATABASE_URL="postgres://postgres:password@{your-project-id}.supabase.opentrust.net:5432/postgres" TARGET_API_URL="https://your-domain.supabase.opentrust.net" TARGET_ANON_KEY="eyJ..." TARGET_SERVICE_ROLE_KEY="eyJ..." TARGET_DATABASE_URL="postgres://postgres:password@{your-project-id}.supabase.opentrust.net:5432/postgres" EOF # Load the environment variables source migration.env
Step 2: Download the tool and log in
Download the supabase-cli tool for your operating system and architecture. In subsequent commands, replace
supabase-cliwith the name of the downloaded CLI tool.Run the following command and follow the prompts to complete the login.
./supabase-cli login
Step 3: (Optional) Preview migration
If you are not using environment variables and your database password contains special characters, you must escape them.
If the Supabase Cloud database is inaccessible and the error "failed to connect to host=db.xxxx.supabase.co user=postgres database=postgres" is returned, specify the
--source-database-urlparameter as the Transaction pooler address. For details on how to obtain this address, see Step 1: Get project information and set environment variables.
Migrate from Supabase Cloud to AnalyticDB Supabase
./supabase-cli migrate-project \ --source-project-ref "$SOURCE_PROJECT_REF" \ --source-anon-key "$SOURCE_ANON_KEY" \ --source-service-role-key "$SOURCE_SERVICE_ROLE_KEY" \ --target-api-url "$TARGET_API_URL" \ --target-anon-key "$TARGET_ANON_KEY" \ --target-service-role-key "$TARGET_SERVICE_ROLE_KEY" \ --target-database-url "$TARGET_DATABASE_URL" \ --dry-runMigrate from a self-hosted Supabase or AnalyticDB Supabase to AnalyticDB Supabase
./supabase-cli migrate-project \ --source-hosted \ --source-api-url "$SOURCE_API_URL" \ --source-anon-key "$SOURCE_ANON_KEY" \ --source-service-role-key "$SOURCE_SERVICE_ROLE_KEY" \ --source-database-url "$SOURCE_DATABASE_URL" \ --target-api-url "$TARGET_API_URL" \ --target-anon-key "$TARGET_ANON_KEY" \ --target-service-role-key "$TARGET_SERVICE_ROLE_KEY" \ --target-database-url "$TARGET_DATABASE_URL" \ --dry-run
Step 4: Migrate the project
If you are not using environment variables and your database password contains special characters, you must escape them.
If the Supabase Cloud database is inaccessible and the error "failed to connect to host=db.xxxx.supabase.co user=postgres database=postgres" is returned, specify the
--source-database-urlparameter as the Transaction pooler address. For details on how to obtain this address, see Step 1: Get project information and set environment variables.
Complete project
Migrate from Supabase Cloud to AnalyticDB Supabase
./supabase-cli migrate-project \ --source-project-ref "$SOURCE_PROJECT_REF" \ --source-anon-key "$SOURCE_ANON_KEY" \ --source-service-role-key "$SOURCE_SERVICE_ROLE_KEY" \ --target-api-url "$TARGET_API_URL" \ --target-anon-key "$TARGET_ANON_KEY" \ --target-service-role-key "$TARGET_SERVICE_ROLE_KEY" \ --target-database-url "$TARGET_DATABASE_URL"Migrate from a self-hosted Supabase or AnalyticDB Supabase to AnalyticDB Supabase
./supabase-cli migrate-project \ --source-hosted \ --source-api-url "$SOURCE_API_URL" \ --source-anon-key "$SOURCE_ANON_KEY" \ --source-service-role-key "$SOURCE_SERVICE_ROLE_KEY" \ --source-database-url "$SOURCE_DATABASE_URL" \ --target-api-url "$TARGET_API_URL" \ --target-anon-key "$TARGET_ANON_KEY" \ --target-service-role-key "$TARGET_SERVICE_ROLE_KEY" \ --target-database-url "$TARGET_DATABASE_URL"
Database schema and data
Use themigrate-database subcommand to migrate only the database schema and data.
The following additional parameters are supported:
--include-data: Specifies whether to include data.--include-system-data: Specifies whether to include system data.--allow-truncate: Specifies whether to allow clearing table data.--preserve-extra-tables: Specifies whether to preserve extra tables.
The following examples show how to use this subcommand:
Migrate from Supabase Cloud to AnalyticDB Supabase
./supabase-cli migrate-project migrate-database \ --source-project-ref "$SOURCE_PROJECT_REF" \ --source-anon-key "$SOURCE_ANON_KEY" \ --source-service-role-key "$SOURCE_SERVICE_ROLE_KEY" \ --target-api-url "$TARGET_API_URL" \ --target-anon-key "$TARGET_ANON_KEY" \ --target-service-role-key "$TARGET_SERVICE_ROLE_KEY" \ --target-database-url "$TARGET_DATABASE_URL"Migrate from a self-hosted Supabase or AnalyticDB Supabase to AnalyticDB Supabase
./supabase-cli migrate-project migrate-database \ --source-hosted \ --source-api-url "$SOURCE_API_URL" \ --source-anon-key "$SOURCE_ANON_KEY" \ --source-service-role-key "$SOURCE_SERVICE_ROLE_KEY" \ --source-database-url "$SOURCE_DATABASE_URL" \ --target-api-url "$TARGET_API_URL" \ --target-anon-key "$TARGET_ANON_KEY" \ --target-service-role-key "$TARGET_SERVICE_ROLE_KEY" \ --target-database-url "$TARGET_DATABASE_URL"
Storage buckets and objects
Use themigrate-storage subcommand to migrate only storage buckets and objects.
Migrate from Supabase Cloud to AnalyticDB Supabase
./supabase-cli migrate-project migrate-storage \ --source-project-ref "$SOURCE_PROJECT_REF" \ --source-anon-key "$SOURCE_ANON_KEY" \ --source-service-role-key "$SOURCE_SERVICE_ROLE_KEY" \ --target-api-url "$TARGET_API_URL" \ --target-anon-key "$TARGET_ANON_KEY" \ --target-service-role-key "$TARGET_SERVICE_ROLE_KEY" \ --target-database-url "$TARGET_DATABASE_URL"Migrate from a self-hosted Supabase or AnalyticDB Supabase to AnalyticDB Supabase
./supabase-cli migrate-project migrate-storage \ --source-hosted \ --source-api-url "$SOURCE_API_URL" \ --source-anon-key "$SOURCE_ANON_KEY" \ --source-service-role-key "$SOURCE_SERVICE_ROLE_KEY" \ --source-database-url "$SOURCE_DATABASE_URL" \ --target-api-url "$TARGET_API_URL" \ --target-anon-key "$TARGET_ANON_KEY" \ --target-service-role-key "$TARGET_SERVICE_ROLE_KEY" \ --target-database-url "$TARGET_DATABASE_URL"
Edge Functions
Use themigrate-functions subcommand or the functions-cli tool to migrate only Edge Functions.
Migrate from Supabase Cloud to AnalyticDB Supabase
./supabase-cli migrate-project migrate-functions \ --source-project-ref "$SOURCE_PROJECT_REF" \ --source-anon-key "$SOURCE_ANON_KEY" \ --source-service-role-key "$SOURCE_SERVICE_ROLE_KEY" \ --target-api-url "$TARGET_API_URL" \ --target-anon-key "$TARGET_ANON_KEY" \ --target-service-role-key "$TARGET_SERVICE_ROLE_KEY" \ --target-database-url "$TARGET_DATABASE_URL"Migrate from a self-hosted Supabase or AnalyticDB Supabase to AnalyticDB Supabase
./supabase-cli migrate-project migrate-functions \ --source-hosted \ --source-api-url "$SOURCE_API_URL" \ --source-anon-key "$SOURCE_ANON_KEY" \ --source-service-role-key "$SOURCE_SERVICE_ROLE_KEY" \ --source-database-url "$SOURCE_DATABASE_URL" \ --target-api-url "$TARGET_API_URL" \ --target-anon-key "$TARGET_ANON_KEY" \ --target-service-role-key "$TARGET_SERVICE_ROLE_KEY" \ --target-database-url "$TARGET_DATABASE_URL"
FAQ
Resolve "connections refused" error
Run the following command to check network connectivity.
# Check network connectivity
ping db.your-project-ref.supabase.co
# Check the database URL format
# Correct format: postgres://postgres:password@host:port/databaseResolve "permission denied" error
Ensure that you are using the service role key, not the anonymous key.
Check whether the key has sufficient permissions. For permission requirements, see Prerequisites.
Confirm that the target database user has administrator permissions.
Resolve "plugin not available" error
Install the missing plugin in the target database, or remove the unnecessary plugin from the source database.
Resolve "relation already exists" error
Use the following command:
# Use a safer table cleanup policy
supabase migrate-project ... --preserve-extra-tables=true --allow-truncate=trueHandle special characters in connection strings
Configuring project information as environment variables is recommended. Otherwise, you must escape any special characters in your password as follows:
! : %21
@ : %40
# : %23
$ : %24
% : %25
^ : %5e
& : %26
* : %2a
( : %28
) : %29
_ : %5f
+ : %2b
= : %3d