all posts

Top 8 MySQL Hosting Platforms in 2026

Ajay Kumar··8 min read

MySQL is the database people stop thinking about. Choosing where to run it feels like choosing where to buy electricity. Then a migration lands and you find your provider pins 8.0, your recovery window is five days rather than thirty, your read replica is nine seconds behind during the nightly batch, and your old collation does not exist on the new server.

I'm Ajay, I build PandaStack. Conflict of interest up front: we do not sell a managed MySQL service. Our managed database product is Postgres 16 and nothing else — no MySQL button in the dashboard, none coming this quarter. Treat this as a map of shapes, not a price sheet: versions, limits and pricing move on each vendor's schedule.

What you are actually choosing between

A MySQL host answers four questions for you: how compatible with stock MySQL is it really, what happens when a machine dies, how long a restore of your real data takes, and how much ops work is left over. The answers cluster into three families — hyperscaler managed services, MySQL-compatible distributed systems, and self-hosting.

The eight options

1. Amazon RDS for MySQL and Aurora MySQL

RDS is the boring, correct answer for a lot of teams: community MySQL on EBS, automated backups, binlog-based PITR, Multi-AZ with a synchronous standby, promotable read replicas, and parameter groups covering most of my.cnf. On an AWS-shaped stack its IAM and CloudWatch integration matters more than any database feature does.

Aurora wears the same wire protocol but is a different animal. Its storage spans three availability zones and replicas read that storage instead of replaying a binlog, so lag is usually milliseconds and failover is fast. The trade: Aurora is MySQL-compatible rather than MySQL; internals and version timelines differ.

2. Google Cloud SQL for MySQL

The same shape on GCP: managed community MySQL, regional HA with a standby in a second zone, read replicas, binlog-driven PITR. IAM database authentication hands out identities instead of passwords, and the Auth Proxy gives an authorised encrypted connection without a public IP.

3. Azure Database for MySQL — Flexible Server

Azure's current-generation service: community MySQL with zone-redundant HA, read replicas, tiers from burstable to memory-optimised. The feature I wish others copied is stop/start — stop a server outright and stop paying for compute, which makes it usable for staging.

4. PlanetScale

MySQL-compatible, built on Vitess — the sharding and proxy layer built to scale MySQL at YouTube. Its defining feature is workflow, not scale: databases have branches, schema changes go through a deploy request reviewed like a pull request, and online-schema-change machinery applies them without the long metadata locks that make ALTER TABLE on a big InnoDB table an outage. The cost: you talk to Vitess rather than a mysqld, so routing and a few behaviours differ.

5. DigitalOcean Managed MySQL

The mid-market option, whose control panel you can understand in a single sitting: managed MySQL 8 with daily backups, standby nodes for HA, read replicas and encryption. Small team, app on Droplets, tens of gigabytes of data — less cognitive load is a real feature.

6. Aiven for MySQL

Aiven runs managed MySQL on AWS, GCP, Azure, DigitalOcean and others, answering a specific question: managed databases without tying yourself to one hyperscaler's control plane. You get PITR, read replicas, service forking for cheap production copies, and portability between clouds.

7. Oracle MySQL HeatWave

The first-party option, from the people who own MySQL. Its distinguishing feature is HeatWave itself: an in-memory query accelerator on the same instance, for analytical queries against operational data without exporting to a warehouse. Worth a look when reporting is crushing your OLTP database.

8. Self-hosting MySQL on a VM or microVM

This is where PandaStack fits, and the honest version is narrower than the one I could sell you. We do not offer managed MySQL. We offer a Firecracker microVM with a full Ubuntu 24.04 userland where you are root — apt install mysql-server works as on any Linux box, a durable volume keeps the data directory across restarts, and port 3306 is yours. Sandboxes restore from snapshot with a p50 of 179ms.

That fits CI, previews, per-branch test databases and migration rehearsals. It is not a managed HA service: no automated failover, no managed backups, nobody paging themselves when mysqld OOMs at 3am. If MySQL is your system of record, buy one of the seven above. The same is true on EC2 — this is a category, not a pitch.

If you are choosing fresh rather than migrating an existing MySQL app, our managed Postgres 16 does exist — a dedicated microVM per database with a durable volume, PITR via clone, branching, failover and idle auto-suspend. That is a real recommendation for greenfield work and a bad one if you already have ten years of MySQL-specific SQL.

The four differences that actually bite

Connection handling

MySQL uses a thread per connection — cheaper than Postgres's process-per-connection model, but not free: several buffers are allocated per connection on demand. Managed providers set max_connections from instance size, and small instances are tighter than people expect. Serverless functions will find that ceiling for you.

Version pinning, engines and collations

Use InnoDB; MyISAM has no transactions and is not crash-safe. Check which major versions a provider offers and how it handles forced upgrades — managed services move on their own timeline. The landmine on any 5.7-to-8.0 move is character sets: utf8mb4 with the 8.0 default collation differs from the legacy three-byte utf8, and mixed collations produce Illegal mix of collations errors on joins that worked fine yesterday.

Backups and point-in-time recovery

Nearly every managed option here does snapshot plus binlog replay. The differences surface under pressure: retention window length, whether you can restore into a new instance rather than over the existing one, and how long a restore actually takes. A backup you have never restored is a hypothesis.

Read replicas and lag

Standard MySQL replication is asynchronous, so a replica falls behind by an amount that depends on your write pattern. Read-after-write on a replica eventually returns stale data, and it arrives as user confusion rather than an error. Shared-storage designs like Aurora largely remove this. Watch Seconds_Behind_Source.

The two checks to run on day one

Connect with TLS actually verified, then look at the engine before trusting it. MySQL clients have long been happy to encrypt a connection without checking who is on the other end.

# Connect with the certificate actually verified, not just "encrypted".
mysql \
  --host=your-instance.example.com \
  --port=3306 \
  --user=app \
  --ssl-mode=VERIFY_IDENTITY \
  --ssl-ca=/etc/ssl/certs/provider-ca.pem \
  --database=appdb

# --ssl-mode=REQUIRED encrypts but does NOT validate the server certificate.
# VERIFY_IDENTITY checks the CA and that the hostname matches. Use it.
-- What am I actually connected to?
SELECT VERSION(), @@version_comment, @@default_storage_engine;

-- Connection headroom. Max_used_connections is the high-water mark since the
-- last restart: close to max_connections means you are one spike away from
-- "Too many connections".
SHOW GLOBAL VARIABLES LIKE 'max_connections';
SHOW GLOBAL STATUS  LIKE 'Threads_connected';
SHOW GLOBAL STATUS  LIKE 'Max_used_connections';

-- Anything still on MyISAM has no transactions and no crash safety.
SELECT ENGINE, COUNT(*) AS tables
FROM information_schema.TABLES
WHERE TABLE_SCHEMA NOT IN ('mysql','information_schema','performance_schema','sys')
GROUP BY ENGINE;

-- The single most useful operational dump in MySQL. Read TRANSACTIONS for lock
-- waits, LATEST DETECTED DEADLOCK for the last deadlock, and BUFFER POOL AND
-- MEMORY for hit rate and free pages.
SHOW ENGINE INNODB STATUS\G

-- On a replica: how stale are the reads you are about to route here?
SHOW REPLICA STATUS\G
SHOW ENGINE INNODB STATUS only reports the last detected deadlock, not a history. If deadlocks matter, turn on innodb_print_all_deadlocks so they land in the error log where you can count them — assuming your managed provider exposes that parameter and that log.

Running MySQL yourself in a microVM, for CI and previews

The self-hosted entry, made concrete. This runs inside a persistent PandaStack sandbox on the base template, and nothing in it is clever — that is the point.

#!/usr/bin/env bash
# Runs inside a persistent PandaStack sandbox (base template, Ubuntu 24.04).
# You are root in a real Linux userland, so this is just installing MySQL.
set -euo pipefail

export DEBIAN_FRONTEND=noninteractive
apt-get update -qq
apt-get install -y mysql-server

# Keep the data directory on the durable volume, not the ephemeral rootfs.
install -d -o mysql -g mysql /mnt/data/mysql

cat > /etc/mysql/mysql.conf.d/pandastack.cnf <<'CNF'
[mysqld]
datadir                        = /mnt/data/mysql
bind-address                   = 0.0.0.0
default_storage_engine         = InnoDB
character_set_server           = utf8mb4
collation_server               = utf8mb4_0900_ai_ci
max_connections                = 200
# base template guests are 4 GiB; leave room for everything else.
innodb_buffer_pool_size        = 2G
# 2 = flush once a second. Great for CI, wrong for a system of record.
innodb_flush_log_at_trx_commit = 2
CNF

# First boot only: initialise the datadir on the volume.
if [ ! -d /mnt/data/mysql/mysql ]; then
  mysqld --initialize-insecure --user=mysql --datadir=/mnt/data/mysql
fi

mysqld --daemonize --user=mysql
until mysqladmin ping --silent; do sleep 0.5; done

mysql -e "CREATE DATABASE IF NOT EXISTS appdb
            CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci;
          CREATE USER IF NOT EXISTS 'app'@'%'
            IDENTIFIED BY '${MYSQL_APP_PASSWORD}';
          GRANT ALL PRIVILEGES ON appdb.* TO 'app'@'%';
          FLUSH PRIVILEGES;"

echo "mysql up: $(mysql -N -B -e 'SELECT VERSION()')"

Two lines are load-bearing. The data directory sits on the durable volume, so a restart does not take the schema with it. And innodb_flush_log_at_trx_commit is 2, trading durability for speed — fine for a throwaway CI database, wrong where a lost transaction matters.

Choosing in ten minutes

  1. Decide whether MySQL is your system of record. If losing it means losing the business, you need automated failover and self-hosting is out.
  2. Follow your compute. One cloud for everything means that cloud's managed MySQL removes a networking, identity and billing problem at once.
  3. Ask whether your real pain is schema changes. If ALTER TABLE is what your team dreads, PlanetScale aims at exactly that.
  4. Write down your required PITR window and acceptable restore time, then check both against the shortlist.
  5. Decide separately where ephemeral MySQL lives. CI and previews rarely need the same product as production.

The short version

RDS if you are on AWS; Aurora if replica lag and failover speed matter. Cloud SQL and Azure Flexible Server are the same shape with a different identity system. PlanetScale if schema changes are the bottleneck, DigitalOcean for less surface area, Aiven to avoid picking a hyperscaler, HeatWave if analytics on operational data is the problem. Self-hosting for environments meant to be disposable. We do not run a managed MySQL and will not pretend a sandbox is one — what a sandbox is good at is being a MySQL you can create in under a second, break on purpose, and delete without a ticket.

Frequently asked questions

Does PandaStack offer managed MySQL?

No. Our managed database product is Postgres 16 only — there is no managed MySQL service and none is planned for this quarter. What you can do is run MySQL yourself inside a PandaStack sandbox or app microVM. You get root on a full Ubuntu 24.04 userland, so apt install mysql-server works normally, a durable volume keeps the data directory across restarts, and you can bind port 3306. That suits CI, preview environments and self-managed setups. It is not a managed HA service: no automated failover, no managed backups, and nobody on call but you.

What is the difference between Amazon RDS for MySQL and Aurora MySQL?

RDS runs community MySQL on EBS storage with binlog-based replication, so read replicas replay a log and can fall behind under write-heavy load. Aurora replaces the storage layer with a distributed service replicated across three availability zones, and replicas read the same storage as the writer, which is why Aurora replica lag is typically milliseconds and failover is faster. The trade is compatibility: Aurora is MySQL-compatible rather than stock MySQL, so some engine internals, parameters and version timelines differ. Verify the specific features and version you depend on before assuming a drop-in migration.

Is PlanetScale really MySQL?

It is MySQL-compatible, built on Vitess — the sharding and connection-proxy layer originally developed to scale MySQL at YouTube. Your application speaks the MySQL wire protocol, but queries route through Vitess rather than straight to a single mysqld, so connection handling and a small set of MySQL behaviours differ from a standalone server. The upside is workflow: database branches and deploy requests let schema changes be reviewed like pull requests and applied through online-schema-change machinery, avoiding the long metadata locks that make ALTER TABLE on a large InnoDB table an outage.

How many connections can a MySQL server handle?

It depends on RAM more than on any published number. MySQL uses a thread per connection rather than a process, so connections are cheaper than in Postgres, but several buffers are allocated per connection on demand, so max_connections interacts with memory under load. Managed providers set max_connections as a function of instance size, and small instances are tighter than people expect. Check Max_used_connections, the high-water mark since the last restart — if it is near your limit you are one traffic spike from failures. Put ProxySQL or your provider's pooler in front of anything that scales horizontally.

Can I use MySQL for CI and previews but a managed service for production?

Yes, and it is usually the right split. Ephemeral databases have completely different requirements from a system of record: you want them created in seconds, reset without a ticket, and thrown away after the test run, with no need for HA or long backup retention. Running MySQL yourself in a microVM or VM covers that cheaply, with settings like innodb_flush_log_at_trx_commit=2 that you would never use in production. Keep versions and collations matched to production so schema migrations behave the same way in both places.

What breaks most often when migrating MySQL between hosts?

Character sets and collations, by a wide margin. Moving from the legacy three-byte utf8 to utf8mb4, or between 5.7 and 8.0 defaults, produces Illegal mix of collations errors on joins that worked yesterday. After that: max_connections lower on the new instance than the old one, parameters your old my.cnf set that the managed provider does not expose, tables still on MyISAM that quietly break transactional expectations, and PITR retention windows shorter than you assumed. Dump the schema, compare collations column by column, and test a restore before cutting over.

Keep reading

Run code in a microVM in one API call.

49ms p50 cold start. Fork, snapshot, and scale to zero.

Start free
Written by Ajay Kumar, Founder, PandaStack.