Back to Coolify Series
    Part 3 of 6

    Database & Service Management

    Spin up PostgreSQL, MySQL, Redis, and MongoDB. Connect databases to your apps securely and configure automated backups so you never lose data.

    Databases
    Backups
    ⏱️ 20 min
    1

    Databases in Coolify

    Coolify treats databases as first-class resources. Instead of manually running docker run postgres, you click a button, configure a few options, and get a production-ready database with:

    • Persistent storage that survives container restarts
    • Internal networking for secure app connections
    • Backup scheduling with multiple destinations
    • Resource limits to prevent runaway queries

    Supported Databases

    PostgreSQL, MySQL/MariaDB, MongoDB, Redis, KeyDB, Dragonfly, ClickHouse, and more.

    2

    Deploying PostgreSQL

    PostgreSQL is the go-to choice for most applications. Let's spin one up.

    Create the Database

    1. Go to Projects → Select your project (or create one called "Databases")
    2. Click Add ResourceDatabasePostgreSQL
    3. Configure the basics (see table below)
    4. Click Create
    SettingRecommended Value
    Namepostgres-main
    Version16 (latest stable)
    Default Databaseapp_production
    Usernameapp_user
    Password(auto-generated or set your own)

    Resource Configuration

    Recommended settings for a 4GB RamNode VPS:

    SettingValueWhy
    Memory Limit1GPrevents Postgres from starving other services
    Memory Reservation512MGuaranteed minimum
    CPU Limit2Allows burst for complex queries

    Persistent Storage: Coolify automatically creates a persistent volume at /var/lib/postgresql/data. Data survives container restarts, upgrades, and redeployments.

    3

    Connecting Apps to Databases

    Your apps and databases run in Docker containers. Coolify makes connecting them straightforward through internal networking.

    Internal Connection URLs

    Every database resource shows its connection details:

    PostgreSQL Internal Connection
    Internal URL: postgres-main:5432
    Database: app_production
    Username: app_user
    Password: ••••••••••

    The internal URL uses the container name as the hostname. This works because Coolify places resources in the same Docker network.

    Configure Your App's Environment

    Environment Variables
    DATABASE_URL=postgresql://app_user:your-password@postgres-main:5432/app_production

    Or individual variables if your framework prefers:

    Individual Variables
    DB_HOST=postgres-main
    DB_PORT=5432
    DB_NAME=app_production
    DB_USER=app_user
    DB_PASSWORD=your-password

    Connection String Formats

    Node.js (pg, Prisma, Drizzle)
    postgresql://user:password@postgres-main:5432/database
    Django (settings.py)
    Django Configuration
    DATABASES = {
        'default': {
            'ENGINE': 'django.db.backends.postgresql',
            'HOST': os.environ.get('DB_HOST'),
            'PORT': os.environ.get('DB_PORT', 5432),
            'NAME': os.environ.get('DB_NAME'),
            'USER': os.environ.get('DB_USER'),
            'PASSWORD': os.environ.get('DB_PASSWORD'),
        }
    }
    Laravel (.env)
    Laravel Environment
    DB_CONNECTION=pgsql
    DB_HOST=postgres-main
    DB_PORT=5432
    DB_DATABASE=app_production
    DB_USERNAME=app_user
    DB_PASSWORD=your-password
    4

    Deploying MySQL/MariaDB

    Some applications require MySQL. The process is nearly identical to PostgreSQL.

    1. Add ResourceDatabaseMySQL (or MariaDB)
    2. Configure (see table below)
    3. Click Create
    SettingValue
    Namemysql-main
    Version8.0
    Root Password(set a strong password)
    Default Databaseapp_production

    MySQL Connection Strings

    Node.js (mysql2)
    mysql://app_user:password@mysql-main:3306/app_production
    WordPress (wp-config.php)
    define('DB_HOST', 'mysql-main');
    define('DB_NAME', 'app_production');
    define('DB_USER', 'app_user');
    define('DB_PASSWORD', 'your-password');
    5

    Deploying Redis

    Redis serves as a cache, session store, message broker, or queue backend. It's essential for scaling applications.

    1. Add ResourceDatabaseRedis
    2. Configure: Name (redis-cache), Version (7), Password
    3. Click Create

    Redis Connection

    Connection URL
    redis://:your-password@redis-cache:6379
    Node.js (ioredis)
    const redis = new Redis({
      host: 'redis-cache',
      port: 6379,
      password: process.env.REDIS_PASSWORD
    });
    Python (redis-py)
    import redis
    r = redis.Redis(host='redis-cache', port=6379, password=os.environ['REDIS_PASSWORD'])

    Redis for Different Use Cases

    Consider separate Redis instances for different purposes:

    InstanceUse CaseMemory Limit
    redis-cacheApplication caching256M-512M
    redis-sessionsUser session storage128M-256M
    redis-queueJob queue (Sidekiq, Bull)256M-512M
    6

    Deploying MongoDB

    For document-based storage or when your app requires MongoDB specifically.

    1. Add ResourceDatabaseMongoDB
    2. Configure: Name (mongo-main), Version (7), Root Username, Root Password
    3. Click Create

    MongoDB Connection

    Connection URL
    mongodb://admin:password@mongo-main:27017/app_production?authSource=admin
    Node.js (Mongoose)
    mongoose.connect(process.env.MONGODB_URL);
    Python (pymongo)
    client = MongoClient(os.environ['MONGODB_URL'])
    7

    Database Backups

    Data without backups is data waiting to be lost. Coolify provides automated backup scheduling with multiple destination options.

    Enable Scheduled Backups

    1. Go to your database resource → Backups
    2. Click Add Backup
    3. Configure the schedule (see table below)
    ScheduleCron ExpressionUse Case
    Every 6 hours0 */6 * * *High-change production data
    Daily at 3 AM0 3 * * *Standard production
    Weekly Sunday 2 AM0 2 * * 0Low-change databases

    💾 Local Backups

    Stored on your VPS filesystem at /data/coolify/backups. Set retention to keep last 7 backups.

    Warning: Local backups don't protect against disk failure. Use S3-compatible storage for disaster recovery.

    ☁️ S3-Compatible Storage

    Works with AWS S3, Backblaze B2 (just $0.006/GB), Wasabi, MinIO, or any S3-compatible provider.

    1. Go to SettingsStorageAdd Storage
    2. Configure endpoint, bucket, region, access key, secret key
    3. Assign to your database backups

    Backup Verification

    Periodically test your backups:

    Test PostgreSQL backup locally
    # Spin up a temporary container
    docker run -d --name test-restore -e POSTGRES_PASSWORD=test postgres:16
    docker cp backup.sql test-restore:/backup.sql
    docker exec test-restore psql -U postgres -f /backup.sql
    docker exec test-restore psql -U postgres -c "SELECT COUNT(*) FROM users;"
    docker rm -f test-restore
    8

    External Database Access

    Sometimes you need to connect directly—running migrations, using a GUI client, or debugging.

    ⚠️ Expose Database Port (Temporary)

    1. Database settings → Network
    2. Enable Publicly Accessible
    3. Set a non-standard port (e.g., 35432)

    Disable when not needed. Use strong passwords and consider IP allowlisting.

    ✅ SSH Tunnel (Recommended)

    Safer than exposing ports—tunnel through SSH:

    SSH Tunnel
    ssh -L 5432:postgres-main:5432 root@your-server-ip

    Connect your local client to localhost:5432. Connection is encrypted and the database port stays closed.

    GUI clients with built-in SSH: TablePlus, DBeaver, DataGrip, pgAdmin

    9

    Running Migrations

    Most frameworks include migration tools. Run them either during deployment or manually.

    Option 1: Post-Deploy Command

    Add to your app's settings. Runs automatically after each successful deployment:

    Post-Deploy Commands
    # Node.js (Prisma)
    npx prisma migrate deploy
    
    # Python (Alembic)
    alembic upgrade head
    
    # Laravel
    php artisan migrate --force
    
    # Rails
    rails db:migrate

    Option 2: One-Off Commands

    For manual migration runs:

    Manual Migration
    # SSH to your server
    ssh root@your-server-ip
    
    # Execute command in your app's container
    docker exec -it <app-container-id> npx prisma migrate deploy

    Or use Coolify's Execute Command feature in the resource settings.

    10

    Database Management Tips

    🔄 Connection Pooling

    If your app opens many connections, deploy PgBouncer as a separate service. Benefits: handles thousands of connections, reduces PostgreSQL memory usage, faster connection establishment.

    📊 Basic Monitoring

    Monitoring Commands
    # PostgreSQL: Active connections
    docker exec -it <postgres> psql -U postgres -c "SELECT * FROM pg_stat_activity;"
    
    # MySQL: Process list
    docker exec -it <mysql> mysql -u root -p -e "SHOW PROCESSLIST;"
    
    # Redis: Memory and stats
    docker exec -it <redis> redis-cli INFO

    For comprehensive monitoring, deploy Prometheus + Grafana (covered in Part 6).

    📁 Multiple Databases per Instance

    Save resources by running staging and production in one instance:

    Create Additional Database
    # PostgreSQL
    docker exec -it <postgres> psql -U postgres -c "CREATE DATABASE staging_db;"
    
    # MySQL
    docker exec -it <mysql> mysql -u root -p -e "CREATE DATABASE staging_db;"

    What's Next

    You now have production databases running alongside your applications, connected through secure internal networking, with automated backups protecting your data.

    In Part 4, we'll deploy complete application stacks using Docker Compose—spinning up popular self-hosted apps like Plausible Analytics, n8n, Uptime Kuma, and more with just a few clicks.