The Convex backend is designed to work with SQLite, PostgreSQL, or MySQL. By default, the Docker image uses SQLite, which is great for getting started. For production workloads requiring guaranteed uptime, we recommend using a managed PostgreSQL or MySQL service.
It’s very important your backend is hosted in the same region and as close as possible to your database. Any additional latency between backend and database will negatively impact query performance.
Supported databases
SQLite : Default, built-in (no configuration needed)
PostgreSQL : Version 17 and compatible versions
MySQL : Version 8 and compatible versions
Migrating between databases
Use npx convex export to export your data before moving from one database provider to another:
npx convex export --path ./backup.zip
After setting up your new database, import the data:
npx convex import --replace-all ./backup.zip
PostgreSQL setup
Using Neon (recommended)
Neon provides managed PostgreSQL with automatic scaling and branching.
Create a database on Neon
Copy the connection string from the Neon dashboard.
Create the Convex database
export DATABASE_CONNECTION = 'postgresql://user:password@host.neon.tech/defaultdb?sslmode=require'
psql $DATABASE_CONNECTION -c "CREATE DATABASE convex_self_hosted"
Set the POSTGRES_URL environment variable
Extract the connection string without the database name and query parameters: export POSTGRES_URL = $( echo $DATABASE_CONNECTION | sed -E 's/\/[^/]+(\?.*)?$//' )
This should result in a URL ending in neon.tech: # Example result
postgresql://user:password@host.neon.tech
Configure your deployment
Add to your .env file: POSTGRES_URL = 'postgresql://user:password@host.neon.tech'
Or set as a secret on your hosting platform: # Fly.io example
fly secrets set POSTGRES_URL= $POSTGRES_URL
Restart the backend
docker compose down
docker compose up
Check the logs for a line like:
Deploy your functions
Redeploy your Convex functions to the new database:
Using local PostgreSQL
For local development:
Create the database
psql postgres -c "CREATE DATABASE convex_self_hosted"
Set environment variables
Create a .env file with your PostgreSQL connection: POSTGRES_URL = 'postgresql://your-username@host.docker.internal:5432'
DO_NOT_REQUIRE_SSL = 1
Only use DO_NOT_REQUIRE_SSL=1 for local development. Production deployments should use SSL.
Custom database names
The database name is derived from your instance name (with - replaced by _):
POSTGRES_URL = 'postgresql://user:password@host.provider.com'
INSTANCE_NAME = 'my-production-instance'
Create the corresponding database:
psql $POSTGRES_URL -c "CREATE DATABASE my_production_instance;"
MySQL setup
Using PlanetScale
PlanetScale provides managed MySQL with Vitess.
Create a database on PlanetScale
Create a database named convex_self_hosted in the PlanetScale dashboard.
Get the connection string
Copy the connection string from PlanetScale. Do not include the database name in MYSQL_URL.
Configure your deployment
Add to your .env file: MYSQL_URL = 'mysql://user:password@aws.connect.psdb.cloud'
Using local MySQL
For local development:
Create the database
mysql -e "CREATE DATABASE convex_self_hosted;"
Set environment variables
Create a .env file: MYSQL_URL = 'mysql://your-username@host.docker.internal:3306'
DO_NOT_REQUIRE_SSL = 1
Only use DO_NOT_REQUIRE_SSL=1 for local development. Production deployments should use SSL.
Database naming conventions
The Convex backend connects to a database with the same name as your instance:
Default instance name: convex-self-hosted
Default database name: convex_self_hosted (hyphens replaced with underscores)
To use a custom database name, set the INSTANCE_NAME environment variable:
INSTANCE_NAME = 'my-app-production'
Then create the corresponding database:
# PostgreSQL
psql $POSTGRES_URL -c "CREATE DATABASE my_app_production;"
# MySQL
mysql -e "CREATE DATABASE my_app_production;"
PostgreSQL
postgresql://[user[:password]@][host][:port][/dbname][?param1=value1&...]
Important : POSTGRES_URL should NOT include the database name or query parameters:
# Correct
POSTGRES_URL = 'postgresql://user:password@host.provider.com'
# Incorrect
POSTGRES_URL = 'postgresql://user:password@host.provider.com/convex_self_hosted?sslmode=require'
MySQL
mysql://[user[:password]@][host][:port][/dbname][?param1=value1&...]
Important : MYSQL_URL should NOT include the database name or query parameters:
# Correct
MYSQL_URL = 'mysql://user:password@host.provider.com'
# Incorrect
MYSQL_URL = 'mysql://user:password@host.provider.com/convex_self_hosted?ssl=true'
Verification
After configuring your database, verify the connection:
Check the logs
Look for connection confirmation: docker compose logs backend | grep -i connected
You should see: or
Deploy functions
Deploy your Convex functions to ensure everything works:
Test the deployment
Run a test query: npx convex run myFunction
Troubleshooting
Connection errors
If you see connection errors in the logs:
Verify the connection string : Ensure it doesn’t include the database name or query parameters
Check region/latency : Ensure your backend is in the same region as your database
Verify SSL settings : Use DO_NOT_REQUIRE_SSL=1 only for local development
Check firewall rules : Ensure your hosting platform can access your database
Database not found
If you see “database not found” errors:
Verify database exists : Check that you created the database with the correct name
Check instance name : Ensure the database name matches your instance name (with hyphens replaced by underscores)
Verify permissions : Ensure your database user has access to the database
Check latency : Use ping or similar tools to measure latency between backend and database
Same region : Ensure backend and database are in the same region
Connection pooling : Managed services typically handle this automatically
Example configurations
Production with Neon PostgreSQL
POSTGRES_URL = 'postgresql://user:password@ep-region-12345.us-east-2.aws.neon.tech'
INSTANCE_NAME = 'my-production-app'
CONVEX_CLOUD_ORIGIN = 'https://api.my-domain.com'
CONVEX_SITE_ORIGIN = 'https://my-domain.com'
Production with PlanetScale MySQL
MYSQL_URL = 'mysql://user:password@aws.connect.psdb.cloud'
INSTANCE_NAME = 'my-production-app'
CONVEX_CLOUD_ORIGIN = 'https://api.my-domain.com'
CONVEX_SITE_ORIGIN = 'https://my-domain.com'
Local development with PostgreSQL
POSTGRES_URL = 'postgresql://postgres@host.docker.internal:5432'
DO_NOT_REQUIRE_SSL = 1
RUST_LOG = debug
Next steps
Storage Configure S3-compatible storage for files and exports
Configuration Explore all runtime configuration options