---
title: "Self-Host Convex in 2026: Docker Compose & Dokploy Setup Guide"
description: "Deploy Convex backend on your VPS with Docker Compose or Dokploy. Covers SQLite, PostgreSQL, MySQL, reverse proxy, S3 storage, and Prometheus metrics. Updated June 2026."
date: 2026-06-12
categories: ["vps"]
tags: ["self-hosted","docker"]
---

If you are building real-time applications with databases, you have probably run into [Convex](https://go.bitdoze.com/convex). It is a backend-as-a-service platform that combines a real-time database with serverless functions. The cloud free tier gives you 0.5GB database storage and 1M function calls per month, which works for small projects. Self-hosting removes those limits and gives you control over your data and infrastructure.

In this guide, I walk through self-hosting Convex using either Dokploy (simpler approach) or Docker Compose (more control). We cover SQLite for smaller setups, and PostgreSQL or MySQL for production.

## What is Convex?

[Convex](https://go.bitdoze.com/convex) is a backend platform that combines databases, API servers, and caching layers into one system. It handles real-time data synchronization, serverless functions, and caching using a TypeScript API.

### Key Features of Convex

<ListCheck>
- **Real-Time Database**: Automatic data synchronization across all clients with reactive queries
- **TypeScript-First**: End-to-end type safety from backend to frontend
- **Serverless Functions**: Write queries, mutations, and actions in TypeScript without managing servers
- **Built-in Scheduling**: Cron jobs and scheduled functions without external services
- **File Storage**: Built-in file upload and storage with CDN distribution
- **Full-Text Search**: Native search capabilities without Elasticsearch
- **Authentication**: Flexible auth system supporting various providers
- **Atomic Transactions**: ACID guarantees for data consistency
- **Time Travel**: Query historical data and debug with time-travel queries
- **Vector Search**: Built-in vector database for AI applications
</ListCheck>

### Why Self-Host Convex?

**Self-hosting advantages**:
- You own the data and control where it lives
- No bandwidth or function execution caps
- Customize infrastructure and scaling
- Lower costs at scale
- Run on-premises or in private networks

**Cloud-Hosted Convex Free Tier**:
- 0.5GB database storage
- 1M function calls per month
- 1GB file storage
- Unlimited projects
- Works well for development and small apps

Consider self-hosting when you hit those limits or need more infrastructure control.

<YouTubeEmbed
  url="https://www.youtube.com/embed/rEcOmzYyb1g"
  label="Self-Host Convex on Your Own Server – Full Step-by-Step Guide"
/>



## Prerequisites

You'll need:

<ListCheck>
- **A VPS or Server**: 2GB RAM minimum, 2 CPU cores (4GB RAM recommended for PostgreSQL)
- **A Domain Name**: For your Convex backend (e.g., `api.yourdomain.com`)
- **Docker Installed**: Docker and Docker Compose (Dokploy includes Docker)
- **Basic Command Line Knowledge**: For running commands
</ListCheck>

<Button text="Try Hetzner Cloud Now" link="https://go.bitdoze.com/hetzner" variant="solid" color="blue" size="lg" external={true} icon="rocket-launch" />
<Button text="Try Hostinger VPS" link="https://go.bitdoze.com/hostinger-vps" variant="solid" color="green" size="lg" external={true} icon="rocket-launch" />

<Notice type="info" title="Hosting Recommendations">
For development, a basic VPS with 2GB RAM works fine with SQLite. For production, use 4GB RAM with PostgreSQL hosted in the same region for optimal performance. Providers like Hetzner, DigitalOcean, or AWS work well.
</Notice>

## Option 1: Deploy with Dokploy (Easiest Method)

Dokploy is an open-source Platform as a Service for deploying applications. **Good news: Dokploy includes a Convex template**. This means you can deploy Convex with a few clicks. If you haven't set up Dokploy yet, check out our [Dokploy Installation Guide](https://www.bitdoze.com/dokploy-install/).

### Method A: Using Dokploy's Built-in Template (Recommended)

This is the fastest way to deploy Convex. Dokploy has a built-in template that you can use as-is or **customize with your own configuration**.

**Step 1: Install Dokploy** (if not already installed)

```sh
curl -sSL https://dokploy.com/install.sh | sh
```

Access Dokploy at `http://your-vps-ip:3000` and complete the setup.

**Step 2: Deploy from Template**

1. Log in to Dokploy dashboard
2. Click **"Create Project"** and name it (e.g., "Convex")
3. Click **"Templates"** in the left sidebar
4. Search for **"Convex"** in the template gallery
5. Click **"Deploy"** on the Convex template

**Step 3: Customize the Configuration** (Optional)

The template comes with a default configuration, but you can override it with your own settings:

1. After deploying the template, go to the **Docker Compose** tab
2. You'll see the template's default YAML - you can edit it if needed
3. Go to the **Environment** tab to set your variables (see below)

<Notice type="info" title="Template Flexibility">
The Dokploy template is a good starting point, but you can customize it by editing the Docker Compose configuration and environment variables.
</Notice>


```yaml
services:
  backend:
    image: ghcr.io/get-convex/convex-backend:latest
    volumes:
      - data:/convex/data
    environment:
      - INSTANCE_NAME=${INSTANCE_NAME:-convex-self-hosted}
      - INSTANCE_SECRET=${INSTANCE_SECRET:-}
      - CONVEX_RELEASE_VERSION_DEV=${CONVEX_RELEASE_VERSION_DEV:-}
      - ACTIONS_USER_TIMEOUT_SECS=${ACTIONS_USER_TIMEOUT_SECS:-}
      - CONVEX_CLOUD_ORIGIN=${CONVEX_CLOUD_ORIGIN:-http://127.0.0.1:3210}
      - CONVEX_SITE_ORIGIN=${CONVEX_SITE_ORIGIN:-http://127.0.0.1:3211}
      - POSTGRES_URL=${POSTGRES_URL:-}
      - DISABLE_BEACON=${DISABLE_BEACON:-true}
      - REDACT_LOGS_TO_CLIENT=${REDACT_LOGS_TO_CLIENT:-}
      - RUST_LOG=${RUST_LOG:-info}
      - RUST_BACKTRACE=${RUST_BACKTRACE:-}
      - DO_NOT_REQUIRE_SSL=${DO_NOT_REQUIRE_SSL:-1}
    healthcheck:
      test: curl -f http://localhost:3210/version
      interval: 5s
      start_period: 5s

  dashboard:
    image: ghcr.io/get-convex/convex-dashboard:latest
    environment:
      - NEXT_PUBLIC_DEPLOYMENT_URL=${NEXT_PUBLIC_DEPLOYMENT_URL:-http://127.0.0.1:3210}
    depends_on:
      backend:
        condition: service_healthy

  postgres:
    image: postgres:17-alpine
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_DB=convex_self_hosted
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  data:
  postgres-data:
```

<Notice type="info" title="SQLite vs PostgreSQL vs MySQL">
This configuration includes PostgreSQL for production. If you prefer SQLite (simpler, works well for development), leave `POSTGRES_URL` and `MYSQL_URL` empty and Convex will use SQLite. For production, set `POSTGRES_URL` to connect to PostgreSQL, or `MYSQL_URL` to connect to MySQL. MySQL support was added in early 2026.
</Notice>


**Step 4: Configure Environment Variables**

Go to the **Environment** tab and add these variables:

**Required:**
- `INSTANCE_SECRET`: Generate with `openssl rand -hex 32`

**URLs** - Choose one option:

**Option A: Use Dokploy's Free Traefik Domains** (Quick start)
```sh
NEXT_PUBLIC_DEPLOYMENT_URL=http://shhosted-convex-cf33fb-91-98-95-196.traefik.me
CONVEX_CLOUD_ORIGIN=http://shhosted-convex-cf33fb-91-98-95-196.traefik.me
CONVEX_SITE_ORIGIN=http://shhosted-convex-59a34c-91-98-95-196.traefik.me
```

**Option B: Use Your Own Domain** (Production)

First, set up DNS A record: `backend.convex.yourdomain.com` → Your VPS IP

Then set:
```sh
CONVEX_CLOUD_ORIGIN=https://api.convex.yourdomain.com
CONVEX_SITE_ORIGIN=https://backend.convex.yourdomain.com
NEXT_PUBLIC_DEPLOYMENT_URL=https://api.convex.yourdomain.com
```

**PostgreSQL** (optional, leave empty to use SQLite):
```sh
DB_PASSWORD=your-strong-password
POSTGRES_URL=postgresql://postgres:your-strong-password@postgres:5432
```



**Step 5: Configure Domain in Dokploy** (if using custom domain)

1. Go to the **Domains** tab
2. Add your domain: `backend.convex.yourdomain.com`
3. Dokploy's Traefik will automatically handle SSL

**Step 6: Deploy and Generate Admin Key**

1. Click **"Deploy"** and wait for services to start
2. Once healthy, click **"Terminal"** to access the backend container
3. Navigate and run:
```sh
cd convex
./generate_admin_key.sh
```
4. Save the admin key securely



## Option 2: Deploy with Docker Compose Only

If you prefer deploying without Dokploy or want more control, here's how to use Docker Compose directly.

### Step 1: Prepare Your Server

Update system and install Docker:

```sh
# Update packages
sudo apt update && sudo apt upgrade -y

# Install Docker
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

# Install Docker Compose
sudo apt install docker-compose -y
```

### Step 2: Create Project Directory

```sh
mkdir -p ~/convex-backend
cd ~/convex-backend
```

### Step 3: Create Docker Compose File

**For SQLite (Simple Setup)**:

```sh
nano docker-compose.yml
```

Paste:

```yaml
services:
  backend:
    image: ghcr.io/get-convex/convex-backend:latest
    stop_grace_period: 10s
    stop_signal: SIGINT
    ports:
      - "3210:3210"
      - "3211:3211"
    volumes:
      - data:/convex/data
    environment:
      - INSTANCE_NAME=${INSTANCE_NAME:-convex-self-hosted}
      - INSTANCE_SECRET=${INSTANCE_SECRET}
      - CONVEX_CLOUD_ORIGIN=${CONVEX_CLOUD_ORIGIN:-http://127.0.0.1:3210}
      - CONVEX_SITE_ORIGIN=${CONVEX_SITE_ORIGIN:-http://127.0.0.1:3211}
      - RUST_LOG=${RUST_LOG:-info}
      - DISABLE_BEACON=${DISABLE_BEACON:-false}
    healthcheck:
      test: curl -f http://localhost:3210/version
      interval: 5s
      start_period: 10s

  dashboard:
    image: ghcr.io/get-convex/convex-dashboard:latest
    stop_grace_period: 10s
    stop_signal: SIGINT
    ports:
      - "6791:6791"
    environment:
      - NEXT_PUBLIC_DEPLOYMENT_URL=${NEXT_PUBLIC_DEPLOYMENT_URL:-http://127.0.0.1:3210}
    depends_on:
      backend:
        condition: service_healthy

volumes:
  data:
```

**For PostgreSQL (Production Setup)**:

```yaml
services:
  backend:
    image: ghcr.io/get-convex/convex-backend:latest
    stop_grace_period: 10s
    stop_signal: SIGINT
    ports:
      - "3210:3210"
      - "3211:3211"
    environment:
      - INSTANCE_NAME=${INSTANCE_NAME:-convex-self-hosted}
      - INSTANCE_SECRET=${INSTANCE_SECRET}
      - CONVEX_CLOUD_ORIGIN=${CONVEX_CLOUD_ORIGIN:-http://127.0.0.1:3210}
      - CONVEX_SITE_ORIGIN=${CONVEX_SITE_ORIGIN:-http://127.0.0.1:3211}
      - POSTGRES_URL=${POSTGRES_URL}
      - DO_NOT_REQUIRE_SSL=${DO_NOT_REQUIRE_SSL:-false}
      - RUST_LOG=${RUST_LOG:-info}
      - DOCUMENT_RETENTION_DELAY=${DOCUMENT_RETENTION_DELAY:-172800}
      - DISABLE_BEACON=${DISABLE_BEACON:-false}
    depends_on:
      postgres:
        condition: service_healthy
    healthcheck:
      test: curl -f http://localhost:3210/version
      interval: 5s
      start_period: 10s

  dashboard:
    image: ghcr.io/get-convex/convex-dashboard:latest
    stop_grace_period: 10s
    stop_signal: SIGINT
    ports:
      - "6791:6791"
    environment:
      - NEXT_PUBLIC_DEPLOYMENT_URL=${NEXT_PUBLIC_DEPLOYMENT_URL:-http://127.0.0.1:3210}
    depends_on:
      backend:
        condition: service_healthy

  postgres:
    image: postgres:17-alpine
    environment:
      - POSTGRES_USER=postgres
      - POSTGRES_PASSWORD=${DB_PASSWORD}
      - POSTGRES_DB=convex_self_hosted
    volumes:
      - postgres-data:/var/lib/postgresql/data
    restart: unless-stopped
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

volumes:
  postgres-data:
```

### Step 4: Create Environment File

```sh
nano .env
```

Add your configuration:

```sh
# Instance Configuration
INSTANCE_NAME=convex-self-hosted
INSTANCE_SECRET=<generate-with-openssl-rand-hex-32>

# Public URLs (update these for production)
CONVEX_CLOUD_ORIGIN=http://127.0.0.1:3210
CONVEX_SITE_ORIGIN=http://127.0.0.1:3211
NEXT_PUBLIC_DEPLOYMENT_URL=http://127.0.0.1:3210

# PostgreSQL Configuration (only if using PostgreSQL)
DB_PASSWORD=<your-secure-db-password>
POSTGRES_URL=postgresql://postgres:${DB_PASSWORD}@postgres:5432
DO_NOT_REQUIRE_SSL=true

# Optional: Logging
RUST_LOG=info

# Optional: Disable telemetry
DISABLE_BEACON=false
```

Generate secrets:
```sh
# Generate instance secret
openssl rand -hex 32
```

### Step 5: Start Convex

```sh
# Start services
docker-compose up -d

# View logs
docker-compose logs -f

# Check status
docker-compose ps
```

### Step 6: Set Up Reverse Proxy with Nginx

For production with custom domains, set up Nginx:

```sh
sudo apt install nginx certbot python3-certbot-nginx -y
```

Create Nginx configuration:

```sh
sudo nano /etc/nginx/sites-available/convex
```

Paste:

```nginx
# Backend API
server {
    listen 80;
    server_name api.yourdomain.com;

    location / {
        proxy_pass http://localhost:3210;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

# Dashboard
server {
    listen 80;
    server_name dashboard.yourdomain.com;

    location / {
        proxy_pass http://localhost:6791;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}
```

Enable site and get SSL:

```sh
# Enable site
sudo ln -s /etc/nginx/sites-available/convex /etc/nginx/sites-enabled/

# Test configuration
sudo nginx -t

# Reload Nginx
sudo systemctl reload nginx

# Get SSL certificates
sudo certbot --nginx -d api.yourdomain.com -d dashboard.yourdomain.com
```

Update your `.env` file with production URLs:

```sh
CONVEX_CLOUD_ORIGIN=https://api.yourdomain.com
CONVEX_SITE_ORIGIN=https://backend.yourdomain.com
NEXT_PUBLIC_DEPLOYMENT_URL=https://api.yourdomain.com
```

Restart services:
```sh
docker-compose down
docker-compose up -d
```

### Step 7: Generate Admin Key

```sh
# Access backend container
docker-compose exec backend /bin/sh

# Navigate to convex directory and generate admin key
cd convex
./generate_admin_key.sh

# Exit container
exit
```

Save the admin key securely - you'll need it for your projects.

## Using Convex in Your Projects

With your self-hosted Convex backend running, here's how to connect your applications.

### Configure Your Project Environment

Add these two environment variables to your application's `.env.local` file (don't commit this to git):

```sh
CONVEX_SELF_HOSTED_URL=https://backend.convex.yourdomain.com
CONVEX_SELF_HOSTED_ADMIN_KEY=convex-self-hosted|015dfa7184876e556124a4ad005ffae7ace340d3d230a5c19106d94c1cdbb183bccf3dee06
```

Replace the URL with your actual backend URL (custom domain or traefik.me URL) and the admin key with the one you generated earlier. The Convex CLI will use your self-hosted backend when these variables are set.


## Advanced Configuration

### Using External PostgreSQL (Neon, Supabase, AWS RDS)

For managed PostgreSQL:

1. Create a database named `convex_self_hosted`
2. Get the connection string (without database name and query params)
3. Update environment:

```sh
POSTGRES_URL=********************************************************
DO_NOT_REQUIRE_SSL=false
```

Example for Neon:
```sh
POSTGRES_URL=**********************************************************************
```

<Notice type="warning" title="Same Region Required">
Put your Convex backend in the same region as your PostgreSQL database. Latency between them will slow down query performance.
</Notice>

### Using MySQL

Convex now supports MySQL as a production database option alongside PostgreSQL. Set the `MYSQL_URL` environment variable:

```sh
MYSQL_URL=mysql://user:password@host:3306/convex_self_hosted
```

This works with managed MySQL from PlanetScale, AWS RDS, or any MySQL 8+ server. The same region advice applies: keep the database close to the Convex backend.

### Monitoring with Prometheus

The self-hosted backend exposes a Prometheus-compatible metrics endpoint at `/metrics`. Enable it by setting:

```sh
DISABLE_METRICS_ENDPOINT=false
```

This gives you request counts, latency histograms, and error rates that you can feed into Grafana or any Prometheus-compatible monitoring stack.

### Tuning Concurrency

The backend exposes environment variables for controlling how many queries, mutations, and actions run at the same time:

```sh
APPLICATION_MAX_CONCURRENT_QUERIES=16
APPLICATION_MAX_CONCURRENT_MUTATIONS=16
APPLICATION_MAX_CONCURRENT_V8_ACTIONS=16
APPLICATION_MAX_CONCURRENT_NODE_ACTIONS=16
```

The default is 16 for each. Increase these if your Convex app handles heavy concurrent traffic and your server has spare CPU and memory.

### Configuring S3 Storage

For production file storage, configure S3:

```yaml
services:
  backend:
    environment:
      # ... other vars ...
      - AWS_REGION=us-east-1
      - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID}
      - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY}
      - S3_STORAGE_EXPORTS_BUCKET=convex-snapshot-exports
      - S3_STORAGE_SNAPSHOT_IMPORTS_BUCKET=convex-snapshot-imports
      - S3_STORAGE_MODULES_BUCKET=convex-modules
      - S3_STORAGE_FILES_BUCKET=convex-user-files
      - S3_STORAGE_SEARCH_BUCKET=convex-search-indexes
```

Create the buckets in AWS S3 or use S3-compatible storage like Cloudflare R2:

```sh
S3_ENDPOINT_URL=https://<account-id>.r2.cloudflarestorage.com
AWS_ACCESS_KEY_ID=<your-r2-access-key>
AWS_SECRET_ACCESS_KEY=<your-r2-secret-key>
```

### Custom Domains for HTTP Actions

To serve HTTP actions from a custom domain:

1. Set up DNS for `api.yourdomain.com`
2. Configure in your environment:

```sh
CONVEX_SITE_ORIGIN=https://api.yourdomain.com
```

3. In your frontend, override the environment variable during build:

```sh
CONVEX_SITE_URL=https://api.yourdomain.com
```

### Migration Between Storage Providers

If switching from SQLite to PostgreSQL or changing S3 configuration:

```sh
# Export data from old backend
npx convex export --path backup.zip

# Deploy new backend with different storage
# ...

# Import data to new backend
npx convex import --replace-all backup.zip
```

## Maintenance and Backups

### Regular Backups

**For Dokploy deployments**, you can configure automated backups through Dokploy's interface or follow our [Dokploy Backups Guide](https://www.bitdoze.com/dokploy-backups-cloudflare-r2/).

**For Docker Compose with PostgreSQL**:

```sh
# Manual backup
docker-compose exec postgres pg_dump -U postgres convex_self_hosted > backup-$(date +%Y%m%d).sql

# Restore backup
cat backup-20241124.sql | docker-compose exec -T postgres psql -U postgres convex_self_hosted
```

**Automated backup script** (`backup.sh`):

```bash
#!/bin/bash
BACKUP_DIR="/backups/convex"
DATE=$(date +%Y%m%d-%H%M)
mkdir -p $BACKUP_DIR

docker-compose exec -T postgres pg_dump -U postgres convex_self_hosted | gzip > $BACKUP_DIR/convex-$DATE.sql.gz

# Keep only last 7 days
find $BACKUP_DIR -name "convex-*.sql.gz" -mtime +7 -delete
```

Make it executable and add to crontab:
```sh
chmod +x backup.sh
crontab -e
# Add: 0 2 * * * /path/to/backup.sh
```

### Updating Convex

**With Dokploy**:
1. Go to your service
2. Click **"Redeploy"**
3. Dokploy pulls latest image and restarts

**With Docker Compose**:
```sh
cd ~/convex-backend
docker-compose pull
docker-compose up -d
```

<Notice type="info" title="Version Pinning">
For production, consider pinning to a specific version instead of `:latest`:

```yaml
image: ghcr.io/get-convex/convex-backend:v0.1.0
```

Check [releases](https://github.com/get-convex/convex-backend/releases) for versions.
</Notice>


## Security Best Practices

<ListCheck>
- **Secure Instance Secret**: Use a strong, random `INSTANCE_SECRET` and never expose it
- **HTTPS Only**: Always use SSL/TLS for production deployments
- **Strong Passwords**: Use complex passwords for PostgreSQL and admin accounts
- **Firewall Configuration**: Only expose necessary ports (80, 443)
- **Regular Updates**: Keep Convex, Docker, and system packages updated
- **Backup Encryption**: Encrypt database backups at rest
- **Environment Variables**: Never commit `.env` files to version control
- **Admin Key Rotation**: Regenerate admin keys periodically
- **Network Isolation**: Use Docker networks to isolate services
- **Monitor Logs**: Set up log monitoring for suspicious activity
</ListCheck>

## Conclusion

Self-hosting Convex gives you control over your real-time backend infrastructure while keeping Convex's developer experience. Whether you use Dokploy or Docker Compose, you can have a production-ready Convex deployment in minutes.

Convex handles real-time queries, serverless functions, file storage, and search. Self-hosting adds infrastructure control to those features. The project is licensed under FSL-1.1 (each release converts to Apache 2.0 after two years) and raised $24M from a16z in November 2025.

For smaller applications, SQLite works well with minimal resources. When you need to scale, PostgreSQL and MySQL handle production workloads more reliably.

### Next Steps

<ListCheck>
- Read the [Convex documentation](https://docs.convex.dev/) for advanced features
- Set up automated backups with our [Dokploy Backups Guide](https://www.bitdoze.com/dokploy-backups-cloudflare-r2/)
- Join the [Convex Discord](https://discord.gg/convex) #self-hosted channel for help
- Consider S3 storage for production file handling
- Monitor your deployment and optimize as needed
</ListCheck>

<Button link="https://go.bitdoze.com/convex" text="Learn More About Convex" />

Questions about self-hosting Convex? Leave a comment below.

## Frequently Asked Questions

<Accordion label="Should I use SQLite or PostgreSQL?" group="faq" expanded="true">
**SQLite** works well for:
- Development and testing
- Small to medium applications (< 10k requests/day)
- Single-server deployments
- Prototypes

**PostgreSQL** is better when:
- You have production workloads with high traffic
- You need high availability
- You want database replication
- You use managed database services (Neon, Supabase, AWS RDS)

Start with SQLite and move to PostgreSQL when you need more reliability.
</Accordion>

<Accordion label="Can I migrate from cloud-hosted Convex to self-hosted?" group="faq">
Yes! The process is straightforward:

1. Export data from cloud: `npx convex export --prod`
2. Set up self-hosted backend
3. Import data: `npx convex import --replace-all`
4. Update environment variables in your frontend
5. Redeploy functions: `npx convex deploy`

Your application code doesn't need to change - just update the backend URL.
</Accordion>

<Accordion label="How much does self-hosting Convex cost?" group="faq">
**Monthly costs** (example):
- VPS with 4GB RAM (Hetzner): $8/month
- PostgreSQL on Neon: Free tier or $19/month for Pro
- Domain: $1/month
- S3 storage (optional): ~$1-5/month

**Total**: $10-30/month

Self-hosting can save money compared to cloud Convex for high-traffic apps.
</Accordion>

<Accordion label="Can I use self-hosted Convex in production?" group="faq">
Absolutely! Many companies run self-hosted Convex in production. Make sure to:

- Use PostgreSQL instead of SQLite
- Set up automated backups
- Configure proper monitoring
- Use SSL/TLS
- Run in a reliable hosting environment
- Keep the backend updated

Follow the production deployment guidelines in this article for a reliable setup.
</Accordion>

<Accordion label="Does self-hosted Convex support all cloud features?" group="faq">
Self-hosted Convex supports all free-tier features:
- Real-time queries and mutations
- Serverless functions
- File storage
- Scheduled functions
- Full-text search
- Vector search
- HTTP actions

The main difference is that you handle infrastructure management: backups, scaling, and maintenance.
</Accordion>

<Accordion label="How do I scale self-hosted Convex?" group="faq">
For vertical scaling:
- Increase VPS resources (CPU/RAM)
- Upgrade to a larger PostgreSQL instance
- Use S3 for file storage

For horizontal scaling:
- Use a managed PostgreSQL with read replicas
- Put Convex behind a load balancer
- Configure multiple backend instances

Most applications won't need horizontal scaling. Vertical scaling handles substantial traffic.
</Accordion>

<Accordion label="Can I use Convex Auth with self-hosted?" group="faq">
Convex Auth works with self-hosted deployments. Follow the [manual setup instructions](https://labs.convex.dev/auth/setup/manual) in the Convex Auth documentation. The CLI's automatic setup doesn't support self-hosted yet.
</Accordion>

<Accordion label="What happens if my backend goes down?" group="faq">
With proper setup:
- Docker restarts crashed containers
- PostgreSQL data persists in volumes
- Recent operations may need to be retried by clients
- Real-time subscriptions reconnect automatically

For high availability:
- Use a monitoring service (UptimeRobot, Pingdom)
- Set up PostgreSQL replication
- Consider running multiple backend instances
- Set up regular automated backups
</Accordion>