Skip to main content
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

Neon provides managed PostgreSQL with automatic scaling and branching.
1

Create a database on Neon

Copy the connection string from the Neon dashboard.
2

Create the Convex database

export DATABASE_CONNECTION='postgresql://user:[email protected]/defaultdb?sslmode=require'
psql $DATABASE_CONNECTION -c "CREATE DATABASE convex_self_hosted"
3

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:[email protected]
4

Configure your deployment

Add to your .env file:
.env
POSTGRES_URL='postgresql://user:[email protected]'
Or set as a secret on your hosting platform:
# Fly.io example
fly secrets set POSTGRES_URL=$POSTGRES_URL
5

Restart the backend

docker compose down
docker compose up
Check the logs for a line like:
Connected to Postgres
6

Deploy your functions

Redeploy your Convex functions to the new database:
npx convex deploy

Using local PostgreSQL

For local development:
1

Create the database

psql postgres -c "CREATE DATABASE convex_self_hosted"
2

Set environment variables

Create a .env file with your PostgreSQL connection:
.env
POSTGRES_URL='postgresql://[email protected]:5432'
DO_NOT_REQUIRE_SSL=1
Only use DO_NOT_REQUIRE_SSL=1 for local development. Production deployments should use SSL.
3

Start the backend

docker compose up

Custom database names

The database name is derived from your instance name (with - replaced by _):
.env
POSTGRES_URL='postgresql://user:[email protected]'
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.
1

Create a database on PlanetScale

Create a database named convex_self_hosted in the PlanetScale dashboard.
2

Get the connection string

Copy the connection string from PlanetScale. Do not include the database name in MYSQL_URL.
3

Configure your deployment

Add to your .env file:
.env
MYSQL_URL='mysql://user:[email protected]'
4

Start the backend

docker compose up

Using local MySQL

For local development:
1

Create the database

mysql -e "CREATE DATABASE convex_self_hosted;"
2

Set environment variables

Create a .env file:
.env
MYSQL_URL='mysql://[email protected]:3306'
DO_NOT_REQUIRE_SSL=1
Only use DO_NOT_REQUIRE_SSL=1 for local development. Production deployments should use SSL.
3

Start the backend

docker compose up

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:
.env
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;"

Connection string format

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:[email protected]'

# Incorrect
POSTGRES_URL='postgresql://user:[email protected]/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:[email protected]'

# Incorrect
MYSQL_URL='mysql://user:[email protected]/convex_self_hosted?ssl=true'

Verification

After configuring your database, verify the connection:
1

Check the logs

Look for connection confirmation:
docker compose logs backend | grep -i connected
You should see:
Connected to Postgres
or
Connected to MySQL
2

Deploy functions

Deploy your Convex functions to ensure everything works:
npx convex deploy
3

Test the deployment

Run a test query:
npx convex run myFunction

Troubleshooting

Connection errors

If you see connection errors in the logs:
  1. Verify the connection string: Ensure it doesn’t include the database name or query parameters
  2. Check region/latency: Ensure your backend is in the same region as your database
  3. Verify SSL settings: Use DO_NOT_REQUIRE_SSL=1 only for local development
  4. Check firewall rules: Ensure your hosting platform can access your database

Database not found

If you see “database not found” errors:
  1. Verify database exists: Check that you created the database with the correct name
  2. Check instance name: Ensure the database name matches your instance name (with hyphens replaced by underscores)
  3. Verify permissions: Ensure your database user has access to the database

Performance issues

  1. Check latency: Use ping or similar tools to measure latency between backend and database
  2. Same region: Ensure backend and database are in the same region
  3. Connection pooling: Managed services typically handle this automatically

Example configurations

Production with Neon PostgreSQL

.env
POSTGRES_URL='postgresql://user:[email protected]'
INSTANCE_NAME='my-production-app'
CONVEX_CLOUD_ORIGIN='https://api.my-domain.com'
CONVEX_SITE_ORIGIN='https://my-domain.com'

Production with PlanetScale MySQL

.env
MYSQL_URL='mysql://user:[email protected]'
INSTANCE_NAME='my-production-app'
CONVEX_CLOUD_ORIGIN='https://api.my-domain.com'
CONVEX_SITE_ORIGIN='https://my-domain.com'

Local development with PostgreSQL

.env
POSTGRES_URL='postgresql://[email protected]: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

Build docs developers (and LLMs) love