Does MySQL Work With Fly.io?
MySQL works excellently with Fly.io through managed database services or self-hosted containers, enabling you to run full-stack applications with persistent data across Fly's global infrastructure.
Quick Facts
How MySQL Works With Fly.io
Fly.io doesn't offer a managed MySQL service directly, but you have two proven patterns: use Fly Postgres (their managed offering) as an alternative, or deploy MySQL in a Docker container on Fly alongside your app. Most developers choose the container approach for MySQL compatibility—you define a Dockerfile for MySQL and deploy it as a separate Fly app, then connect from your main app using Fly's private networking. Alternatively, you can use external managed MySQL (AWS RDS, PlanetScale, DigitalOcean) and connect securely via Fly's WireGuard tunnel or standard TCP connections. The developer experience is smooth: connection strings work identically whether MySQL is co-located or remote. Network latency is negligible for most workloads since Fly's infrastructure spans globally, and you can strategically place your database app in regions closest to your primary users. For high-availability setups, containerized MySQL on Fly works but requires careful volume management—data persistence uses Fly Volumes, which are regional.
Best Use Cases
Quick Setup: Node.js App Connecting to MySQL on Fly
npm install mysql2/promise dotenvimport mysql from 'mysql2/promise';
import dotenv from 'dotenv';
dotenv.config();
const pool = mysql.createPool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
waitForConnections: true,
connectionLimit: 5,
queueLimit: 0
});
// Usage
const connection = await pool.getConnection();
const [rows] = await connection.query('SELECT * FROM users');
console.log(rows);
connection.release();
// In fly.toml, set env vars:
// DB_HOST = "mysql.internal" (if MySQL is another Fly app)
// DB_USER = "root"
// DB_PASSWORD = (your secret)
// DB_NAME = "myapp"Known Issues & Gotchas
MySQL container restarts lose data if no Fly Volume is attached
Fix: Always allocate a persistent volume: 'fly volumes create mysql_data --size 10' and mount it to /var/lib/mysql in your Dockerfile
Single container MySQL has no automatic failover or high availability
Fix: Use managed MySQL (PlanetScale, AWS RDS) for production, or implement Fly Machines with custom health checks and manual replication setup
Regional Fly Volumes can't be accessed from other regions
Fix: Keep your MySQL app and primary app in the same region, or use an external managed service with cross-region replication
Connection pooling is critical—Fly apps can exhaust MySQL connections quickly under load
Fix: Use PgBouncer or implement connection pooling in your application (node-mysql2/promise, Rails ActiveRecord pooling, etc.)
Alternatives
- •PostgreSQL with Fly Postgres (native managed service, simpler operations)
- •PlanetScale (managed MySQL compatible platform, serverless, excellent Fly.io integration)
- •MongoDB Atlas with Fly.io (if you need document database instead of relational)
Resources
Related Compatibility Guides
Explore more compatibility guides