Loading learning content...
Traditional MySQL, even with InnoDB Cluster, was designed for a world of physical servers and on-premises data centers. While it can run in the cloud, it doesn't fully leverage what cloud infrastructure offers: elastic storage, distributed computing, and pay-as-you-go economics.
Cloud-native MySQL offerings rearchitect the database from the ground up to exploit these capabilities. They maintain MySQL compatibility at the SQL layer while introducing fundamentally different storage and replication architectures underneath.
This page examines two transformative approaches:
Amazon Aurora MySQL — AWS's reimplementation of MySQL with distributed storage, delivering up to 5x traditional MySQL performance while maintaining full compatibility.
PlanetScale — A serverless MySQL platform built on Vitess (the technology that powers YouTube's database layer), offering horizontal scaling, non-blocking schema changes, and branching workflows.
Both represent the cutting edge of MySQL in the cloud—understanding their architectures and trade-offs is essential for modern system design.
By the end of this page, you will understand Aurora MySQL's distributed storage architecture, learn PlanetScale's Vitess-based horizontal scaling model, compare architectural decisions and their trade-offs, and develop criteria for choosing between cloud MySQL offerings.
Amazon Aurora MySQL, launched in 2014, rethinks how MySQL storage works. Rather than a single InnoDB tablespace on local disks, Aurora separates compute from storage—the MySQL engine runs on EC2 instances while data lives in a purpose-built, distributed storage layer.
Aurora's Key Innovation: Log-Based Storage
In traditional MySQL, writes follow this path:
Aurora eliminates steps 3 and 4 at the compute layer. Instead:
┌─────────────────────────────────────────────────────────────┐
│ Aurora MySQL Architecture │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Compute Layer (MySQL) │ │
│ │ │ │
│ │ ┌──────────────┐ ┌──────────────┐ │ │
│ │ │ Primary │ │ Replica │ ...more │ │
│ │ │ (R/W) │ │ (R/O) │ replicas │ │
│ │ └──────┬───────┘ └──────┬───────┘ │ │
│ │ │ │ │ │
│ └──────────┼────────────────────┼──────────────────────┘ │
│ │ (redo logs only) │ (read from cache/storage)│
│ ┌──────────▼────────────────────▼──────────────────────┐ │
│ │ Distributed Storage Layer │ │
│ │ │ │
│ │ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ │
│ │ │ AZ-1 │ │ AZ-2 │ │ AZ-3 │ │ │
│ │ │ ○ ○ │ │ ○ ○ │ │ ○ ○ │ │ │
│ │ └─────────┘ └─────────┘ └─────────┘ │ │
│ │ 6 copies of data across 3 Availability Zones │ │
│ │ Quorum writes (4/6), Quorum reads (3/6) │ │
│ └──────────────────────────────────────────────────────┘ │
│ │
│ * Primary sends only redo logs (not full pages) │
│ * Storage applies logs and serves read requests │
│ * Replicas share the same storage (no replication lag!) │
└─────────────────────────────────────────────────────────────┘
Aurora MySQL is wire-protocol compatible with MySQL 5.7 and 8.0. Existing MySQL applications, drivers, and tools work without modification. However, Aurora doesn't support MySQL's pluggable storage engine model—it's Aurora storage only. Features like MyISAM tables aren't available.
Beyond its distributed storage, Aurora offers several unique features that differentiate it from standard MySQL.
Aurora Read Replicas:
Aurora supports up to 15 read replicas, all sharing the same storage. Unlike traditional MySQL replicas, there's no replication lag at the storage level—replicas see writes as soon as they're committed to storage (sub-100ms cache coherence lag).
123456789101112131415161718192021
-- Aurora replicas are created at the cluster level, not via CHANGE REPLICATION SOURCE-- You create them through AWS Console, CLI, or CloudFormation -- Check replica statusSHOW GLOBAL STATUS LIKE 'Aurora_replica%';-- Aurora_replica_status: 0 (connected and healthy) -- Check replica lag (Aurora-specific)SELECT server_id, replica_lag_in_msec, last_update_timestampFROM mysql.ro_replica_status; -- Aurora cluster endpoints-- Writer endpoint: always points to the primary-- mydb-cluster.cluster-xxxxxx.us-east-1.rds.amazonaws.com-- Reader endpoint: load-balanced across replicas-- mydb-cluster.cluster-ro-xxxxxx.us-east-1.rds.amazonaws.com-- Instance endpoints: direct to specific instance-- mydb-instance-1.xxxxxx.us-east-1.rds.amazonaws.comAurora Serverless v2:
Aurora Serverless v2 automatically scales compute capacity based on demand. Unlike provisioned Aurora (fixed instance sizes), Serverless v2 scales in increments of 0.5 ACUs (Aurora Capacity Units) from 0.5 to 128 ACUs.
| Aspect | Behavior | Considerations |
|---|---|---|
| Scaling speed | Scales in seconds, not minutes | Good for variable workloads |
| Minimum capacity | 0.5 ACU (~1GB RAM) | Can't scale to zero; always running |
| Maximum capacity | 128 ACU | Set max to control costs |
| Scaling granularity | 0.5 ACU increments | Fine-grained scaling |
| Mixed configuration | Mix serverless and provisioned | Provisioned for baseline + serverless for spikes |
| Pricing | Per ACU-hour consumed | More expensive than provisioned at steady load |
Aurora Global Database:
For multi-region deployments, Aurora Global Database replicates an Aurora cluster across regions with sub-second replication lag. A primary region handles writes; secondary regions provide local reads and can be promoted for disaster recovery.
Other Aurora Features:
| Feature | Description | Use Case |
|---|---|---|
| Backtrack | Rewind database to a point-in-time without restore | Quick recovery from errors (TRUNCATE TABLE oops) |
| Cloning | Create a copy of database in minutes (copy-on-write) | Dev/test environments; debugging production issues |
| Parallel Query | Push query processing to storage layer | Analytics on operational data |
| Database Activity Streams | Stream database events to Kinesis | Compliance, auditing, security monitoring |
| Machine Learning | Integrate with SageMaker/Comprehend from SQL | ML inference within queries |
Backtrack lets you rewind your database up to 72 hours without restoration from backup. If someone accidentally deletes a table, you can backtrack the entire cluster to 5 minutes ago in seconds. This is immensely valuable for incident recovery. Enable it and configure appropriate retention.
AWS claims Aurora delivers up to 5x the performance of standard MySQL. This claim is nuanced—let's understand when it's true and when it isn't.
When Aurora Is Significantly Faster:
When Aurora and RDS MySQL Perform Similarly:
Aurora Pricing Model:
Aurora pricing is more complex than RDS MySQL. You pay for multiple components:
| Component | Pricing Model | Typical Range |
|---|---|---|
| Instance hours | Per instance size per hour | $0.041/hr (db.t3.small) to $13+/hr (db.r6g.16xlarge) |
| Storage | Per GB-month | $0.10/GB-month |
| I/O operations | Per million I/Os | $0.20 per million I/Os |
| Backup storage | Per GB-month above provisioned | $0.021/GB-month |
| Data transfer | Cross-AZ and internet egress | Standard AWS data transfer rates |
Cost Comparison Example:
For a production database:
RDS MySQL (Multi-AZ):
Aurora MySQL:
Note: These are rough estimates. Actual costs vary by region, instance type, and usage patterns.
Aurora charges per I/O operation. Write-heavy workloads can generate unexpectedly high I/O costs. Monitor IOPS closely when migrating. For predictable, high-I/O workloads, Aurora I/O-Optimized (released 2023) provides predictable pricing by eliminating per-I/O charges for 2.5x storage cost.
PlanetScale takes a fundamentally different approach to cloud MySQL. Built on Vitess—the open-source database clustering system originally developed at YouTube—PlanetScale provides horizontal scaling through sharding while presenting a unified MySQL interface.
The Vitess Foundation:
Vitess was created at YouTube in 2010 to scale MySQL for video metadata. When you watch a YouTube video, Vitess is serving the data. It's been battle-tested at massive scale.
PlanetScale Architecture:
┌─────────────────────────────────────────────────────────────┐
│ PlanetScale Architecture │
│ │
│ ┌─────────────────────────────────────────────────────┐ │
│ │ Application │ │
│ └─────────────────────────┬───────────────────────────┘ │
│ │ │
│ ┌─────────────────────────▼───────────────────────────┐ │
│ │ VTGate │ │
│ │ (Query routing, connection pooling, query │ │
│ │ parsing, shard selection) │ │
│ └─────────────────────────┬───────────────────────────┘ │
│ │ │
│ ┌─────────────┬───────────┴───────────┬───────────────┐ │
│ │ Shard 1 │ Shard 2 │ Shard N │ │
│ │ ┌─────┐ │ ┌─────┐ │ ┌─────┐ │ │
│ │ │MySQL│ │ │MySQL│ │ │MySQL│ │ │
│ │ │+VTT │ │ │+VTT │ │ │+VTT │ │ │
│ │ └─────┘ │ └─────┘ │ └─────┘ │ │
│ │ Primary │ Primary │ Primary │ │
│ │ +Replicas │ +Replicas │ +Replicas │ │
│ └─────────────┴──────────────────────┴───────────────┘ │
│ │
│ VTGate: Stateless query router │
│ VTTablet (VTT): Per-shard agent managing MySQL │
│ Each shard: Independent MySQL with its own replicas │
└─────────────────────────────────────────────────────────────┘
How Sharding Works in PlanetScale:
PlanetScale can shard tables based on a sharding key (vindex). Queries that include the sharding key route to a single shard; queries without it scatter to all shards.
-- Table sharded by user_id
CREATE TABLE orders (
id BIGINT PRIMARY KEY,
user_id BIGINT,
product_id BIGINT,
amount DECIMAL(10,2),
created_at TIMESTAMP
);
-- This query goes to one shard (user_id is sharding key)
SELECT * FROM orders WHERE user_id = 12345;
-- This query scatters to ALL shards (no sharding key)
SELECT * FROM orders WHERE product_id = 999;
-- Scatter queries work but are less efficient
PlanetScale doesn't force sharding. You can run a single unsharded database and still benefit from serverless scaling, branching, and non-blocking schema changes. Sharding is available when you need to scale beyond a single node.
PlanetScale differentiates itself through developer experience features that modernize database workflows.
Database Branching:
PlanetScale introduces Git-like branching for databases. Create a branch, make schema changes, test, then merge back to production—all without taking the database offline.
12345678910111213141516171819202122
# Create a development branch from mainpscale branch create my-database add-user-preferences # Connect to the branch for developmentpscale connect my-database add-user-preferences --port 3307 # Make schema changes on the branchmysql -h 127.0.0.1 -P 3307 -u root << EOFALTER TABLE users ADD COLUMN preferences JSON;CREATE INDEX idx_users_preferences ON users ((CAST(preferences->>'$.theme' AS CHAR(20))));EOF # Create a deploy request (like a pull request for schema)pscale deploy-request create my-database add-user-preferences # The deploy request shows:# - Schema diff# - Compatibility analysis# - Deployment plan # Deploy to production (non-blocking!)pscale deploy-request deploy my-database 1Non-Blocking Schema Changes:
PlanetScale implements online, non-blocking schema changes using a tool called gh-ost (GitHub Online Schema Transformation) under the hood. Unlike ALTER TABLE which can lock tables for hours on large datasets, PlanetScale schema changes:
Safe Migrations (No Foreign Keys):
PlanetScale notably does not support foreign key constraints. This is a deliberate decision for scalability:
| Reason | Explanation |
|---|---|
| Cross-shard complexity | Foreign keys can't span shards; would limit sharding flexibility |
| Online schema changes | FK constraints complicate online migrations significantly |
| Write performance | FK validation adds latency to every write |
| Large-scale operations | Cascading deletes can cause massive I/O spikes |
Other PlanetScale Features:
Without foreign keys, your application code must ensure referential integrity. This is a significant change if you rely on database-level FK enforcement. Many large-scale systems (including YouTube, which Vitess was built for) operate without FKs, but it requires discipline in application logic.
Aurora and PlanetScale represent different philosophies for scaling MySQL in the cloud. Let's compare them across key dimensions.
Architectural Philosophy:
| Aspect | Aurora MySQL | PlanetScale |
|---|---|---|
| Scaling approach | Vertical scaling + read replicas | Horizontal sharding |
| Storage architecture | Distributed, shared storage | Each shard has local storage |
| Maximum size | 128TB per cluster | Virtually unlimited (add shards) |
| Write scaling | Single write endpoint | Multi-shard writes (with sharding key) |
| Foreign keys | Fully supported | Not supported |
| MySQL version control | AWS manages versions/patches | Limited version choice |
Feature Comparison:
| Feature | Aurora MySQL | PlanetScale |
|---|---|---|
| Database branching | Cloning (copy-on-write) | Native branching workflow |
| Non-blocking schema changes | Via pt-online-schema-change (manual) | Built-in with deploy requests |
| Backtrack/undo | Native backtrack up to 72hrs | Deploy request reverts |
| Multi-region | Global Database (async replication) | Read-only regions |
| Serverless | Serverless v2 (scales in seconds) | Always serverless pricing |
| Connection management | RDS Proxy (additional cost) | Built-in |
Operational Comparison:
Choose Aurora if: you need full MySQL compatibility, you're already on AWS, you require FK enforcement, or you need features like Parallel Query. Choose PlanetScale if: you prioritize developer experience, you anticipate needing horizontal scaling, you can live without FKs, or you prefer serverless-first pricing.
Aurora and PlanetScale aren't the only options. Let's briefly cover other significant cloud MySQL offerings.
Google Cloud SQL for MySQL:
Azure Database for MySQL:
Vitess (Self-Managed):
If you want PlanetScale's sharding capabilities but prefer self-hosting:
| Provider | Product | Best For |
|---|---|---|
| AWS | RDS MySQL | Standard MySQL, simple management, AWS ecosystem |
| AWS | Aurora MySQL | High availability, read scaling, large databases |
| Google Cloud | Cloud SQL | Google ecosystem, moderate scale |
| Azure | Azure Database for MySQL | Azure ecosystem, moderate scale |
| PlanetScale | PlanetScale | Developer experience, horizontal scaling, serverless |
| Self-hosted | Vitess on K8s | Maximum control, required expertise |
For many workloads, plain RDS MySQL (not Aurora) is sufficient and cheaper. Multi-AZ RDS provides good availability, and if you don't need Aurora's advanced features, you're paying for complexity you don't use. Start simple and upgrade when needed.
We've explored how cloud-native MySQL offerings reimagine database architecture for modern infrastructure. Let's consolidate the key takeaways:
What's Next:
Now that we've explored MySQL's architecture, replication, comparisons, and cloud offerings, we'll synthesize this knowledge into practical guidance for when to choose MySQL. We'll examine use cases, anti-patterns, and decision frameworks for MySQL selection in real-world systems.
You now understand the architectures of Aurora MySQL and PlanetScale—two different approaches to cloud-native MySQL. This knowledge enables you to choose the right cloud MySQL deployment for your specific requirements, balancing scalability, developer experience, cost, and feature needs.