Quick verdict
Choose MySQL (self-managed, Amazon RDS or Aurora MySQL) when your data is relational, you need joins, unique and foreign keys, or reporting on the same data, and one primary with read replicas can carry the writes. Choose DynamoDB when you are on AWS, access patterns are known and key-based, and you want no servers to manage and throughput that AWS partitions for you. If you are leaving MySQL only because writes no longer fit one server, compare sharding MySQL with Vitess (self-hosted or via PlanetScale) before remodelling the application for DynamoDB.
Amazon DynamoDB is a fully managed NoSQL service that stores items in tables addressed by a partition key and optional sort key. There are no instances or versions to manage, on-demand capacity is the default, items are limited to 400 KB, and it runs only on AWS. Its query model and PartiQL subset are compared with full SQL in DynamoDB vs PostgreSQL; this page focuses on the MySQL side of the decision.
MySQL is Oracle's open source relational database. Community Server is GPLv2, with commercial editions from Oracle; 8.4 and 9.7 are the LTS lines and 26.7 the current Innovation release. Its default engine, InnoDB, provides ACID transactions, row-level locking and enforced primary, unique and foreign keys. On AWS it is available as Amazon RDS for MySQL and as Amazon Aurora MySQL-Compatible Edition.
Side by side
| Aspect | DynamoDB | MySQL |
|---|---|---|
| What it is | Serverless AWS service; AWS only (DynamoDB local for development) | Database software; self-managed, or managed on RDS, Aurora and other clouds |
| Modelling | Access patterns first; related entities often share one table and are grouped by key | Normalised tables joined at query time |
| Uniqueness and references | Only the primary key is unique; no foreign keys | Enforced PRIMARY KEY, UNIQUE and FOREIGN KEY constraints |
| Transactions | Up to 100 items and 4 MB per transaction | InnoDB ACID transactions, REPEATABLE READ by default, no item cap |
| Expiry | Per-item TTL; expired items deleted within a few days, without consuming write throughput | No row TTL; scheduled deletes or partition drops |
| Write scaling | Partitioning handled by AWS | One primary per cluster; horizontal scaling needs sharding (for example Vitess) or MySQL NDB Cluster |
| AWS managed options | DynamoDB itself | RDS for MySQL, Aurora MySQL (8.4 GA May 2026), Aurora Serverless |
| Analytics path | Zero-ETL integration to Amazon Redshift (incremental every 15 to 30 minutes) or exports | SQL on replicas, MySQL HeatWave, or CDC to an analytics database |
| Main trade-off | No servers and automatic scaling, but the schema encodes today's queries | Flexible SQL and constraints, but write scaling past one primary is your problem |
Key differences
Relational tables versus single-table design
A MySQL schema for customers and orders is two tables, a foreign key and a join. New questions are new SQL; constraints keep the data consistent. These statements run as shown on MySQL 8.0 and later:
-- MySQL 8.4: normalised tables with enforced keys
CREATE TABLE customers (
customer_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(100) NOT NULL
);
CREATE TABLE orders (
order_id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
customer_id BIGINT NOT NULL,
order_date DATETIME NOT NULL,
total DECIMAL(10,2) NOT NULL,
FOREIGN KEY (customer_id) REFERENCES customers (customer_id),
INDEX idx_customer_date (customer_id, order_date)
);
-- a report nobody planned for when the schema was designed
SELECT c.name, COUNT(*) AS orders, SUM(o.total) AS revenue
FROM customers AS c
JOIN orders AS o ON o.customer_id = c.customer_id
WHERE o.order_date >= '2026-09-01'
GROUP BY c.customer_id, c.name
ORDER BY revenue DESC
LIMIT 10;DynamoDB has no joins, so related items are commonly stored under the same partition key and told apart by the sort key, so that one key-based read returns a customer and their recent orders. Generic key names such as PK and SK let several entity types share one table:
-- DynamoDB (PartiQL): items in table "Shop"
-- PK = 'CUSTOMER#C123' SK = 'PROFILE' name, email
-- PK = 'CUSTOMER#C123' SK = 'ORDER#2026-09-01#O-1001' total, status
-- one customer's September orders: partition key equality, no scan
SELECT * FROM "Shop"
WHERE PK = 'CUSTOMER#C123' AND begins_with(SK, 'ORDER#2026-09');The DynamoDB design is efficient for the reads it was built for, and the report above has no equivalent: there is no GROUP BY or join, so it needs a scan, a precomputed aggregate or an export to an analytics service. In our view this is the central question: how stable are the queries your application will need?
Constraints and upserts
MySQL enforces uniqueness on any column you declare UNIQUE: a second customer with the same email fails with error 1062 (duplicate entry). DynamoDB guarantees uniqueness only for the primary key. One approach for a second unique attribute is a transaction that also writes an item keyed on that value (for example PK = 'EMAIL#ana@example.com') with an attribute_not_exists condition, which you then have to maintain on every change of email. Referential integrity is likewise application code.
Upserts are natural in both, with different shapes. MySQL's INSERT ... ON DUPLICATE KEY UPDATE (the manual recommends the row alias form shown, because referring to the new row with VALUES() is deprecated) updates in place on a key conflict:
-- MySQL 8.4: add an item to a cart, creating the row if needed
CREATE TABLE carts (user_id BIGINT PRIMARY KEY, item_count INT NOT NULL);
INSERT INTO carts (user_id, item_count) VALUES (42, 1) AS new
ON DUPLICATE KEY UPDATE item_count = carts.item_count + new.item_count;In DynamoDB, PutItem replaces an item by key and UpdateItem creates or modifies one, with condition expressions for optimistic checks. Both work on one item at a time; set-based changes across many rows are a MySQL strength.
Scaling MySQL instead: Aurora MySQL, Vitess and NDB Cluster
Many teams consider DynamoDB because MySQL writes have outgrown one server. There are MySQL-shaped answers first:
- Amazon Aurora MySQL. AWS's MySQL-compatible engine, in which one writer and up to 15 Aurora Replicas share a cluster storage volume. Aurora MySQL 8.4 became generally available on 21 May 2026, compatible with community MySQL 8.4.7 and with version numbers that now match community MySQL; 8.4.8 followed on 3 September 2026. Aurora Serverless adds autoscaling capacity for MySQL as well as PostgreSQL. A cluster still has one writer, and AWS's managed horizontal-scaling options, Aurora PostgreSQL Limitless Database and Aurora DSQL, are PostgreSQL-only. See Amazon Aurora vs MySQL.
- Vitess. An Apache-2.0 project, graduated in the Cloud Native Computing Foundation, that shards MySQL across many instances behind a MySQL-protocol proxy; its documentation says it served all YouTube database traffic for over five years. The application keeps SQL, but cross-shard work has rules: the default transaction mode spans shards with best-effort commits, and atomic cross-shard commits need the
twopcmode, which Vitess says adds commit latency. PlanetScale sells managed Vitess clusters; see PlanetScale vs AWS RDS. - MySQL NDB Cluster. Oracle describes it as a shared-nothing, in-memory distributed database that auto-shards tables across data nodes. It is a different storage engine from InnoDB with its own operational model, so it is a specialist choice.
For a distributed SQL database with MySQL as the comparison point, see CockroachDB vs MySQL. In our view, if the data is relational and the queries are evolving, sharded or scaled MySQL keeps more of what you have than a move to DynamoDB.
Moving from MySQL to DynamoDB
AWS Database Migration Service supports DynamoDB as a target from relational sources including MySQL, using object-mapping rules that build items from columns. Its documented limitations show where the models differ: DynamoDB has no date type (dates become strings), Number precision is limited to 38 digits, primary key attributes cannot be updated (a CDC update to a key can fail or create an incomplete new item), LOBs other than CLOBs are not supported, and composite source keys need an explicit mapping. A table-by-table copy also preserves the relational shape; getting DynamoDB's benefits usually means redesigning keys around access patterns, which is application work, not migration work.
The reverse direction matters too. DynamoDB data used for reporting is usually copied out: the DynamoDB zero-ETL integration with Amazon Redshift exports the table and then replicates changes every 15 to 30 minutes, and needs point-in-time recovery enabled on the source table. With MySQL, the same database (or a replica) answers reports in SQL until volume justifies an analytics engine; see ClickHouse vs MySQL.
Pricing and licensing
DynamoDB. Listed on the AWS DynamoDB on-demand pricing page in October 2026 for US East (N. Virginia), Standard table class, in USD: 0.625 per million write request units and 0.125 per million read request units, plus storage per GB-month. Provisioned capacity, backups, streams, global tables and data transfer are billed separately and vary by Region.
MySQL. Community Server is free under GPLv2; Oracle does not publish commercial edition prices on its product pages. Amazon RDS for MySQL and Aurora MySQL provisioned clusters are billed by instance hours, storage and, for some Aurora configurations, I/O; Aurora Serverless by Aurora capacity units. Use the AWS Pricing Calculator.
PlanetScale (managed Vitess). Listed on PlanetScale's pricing page in October 2026: the smallest Vitess cluster, PS-10 (1/8 vCPU, 1 GiB RAM, one primary and two replicas), at USD 39 per month, with storage and egress beyond what is included billed separately. PlanetScale has no free plan.
Pricing checked on the vendors' official pages on 7 October 2026. Prices change; confirm before buying.
Where each one leads
DynamoDB strengths
- No servers, versions or patching; on-demand capacity by default
- AWS partitions data and scales throughput without sharding work
- Per-item TTL that deletes expired items without consuming write throughput
- Pay-per-request billing suits spiky or low-traffic services
- Zero-ETL integration to Amazon Redshift for analytics
MySQL strengths
- Enforced unique and foreign keys and InnoDB ACID transactions
- Joins, aggregates and ad hoc SQL on the same data
- Runs anywhere; on AWS as RDS for MySQL or Aurora MySQL, now including 8.4
- Horizontal scaling paths that keep SQL: Vitess, PlanetScale, NDB Cluster
- GPLv2 Community Server and a large tool and framework ecosystem
Limitations
DynamoDB limitations
- AWS only
- Uniqueness only on the primary key, and no foreign keys
- No joins or GROUP BY; unplanned queries become scans or exports
- Transactions capped at 100 items and 4 MB; items at 400 KB
MySQL limitations
- One writer per cluster on RDS and Aurora; write scaling beyond it needs sharding
- Sharding with Vitess changes transaction semantics across shards
- You size and operate instances, or pay a managed service to
- No row-level TTL
When to choose each
Choose DynamoDB if
- Your application is on AWS and its access patterns are known and key-based
- You need high or unpredictable write throughput without sharding work
- Entities are self-contained, such as sessions, carts, device state or user profiles
- You want serverless operations and per-request billing
Choose MySQL if
- Your data is relational and integrity rules belong in the database
- Reporting and ad hoc queries run on the same data
- Your framework, ORM or team is built around MySQL
- You want to stay portable across clouds and hosting providers
- Writes fit one primary, or you can shard with Vitess
When neither is right
- You want SQL and a richer feature set than MySQL with a serverless option on AWS: see DynamoDB vs PostgreSQL and MySQL vs PostgreSQL.
- You want a document database with richer queries than DynamoDB: see DynamoDB vs MongoDB and MongoDB vs MySQL.
- You need distributed SQL with multi-region writes: see CockroachDB vs MySQL.
- You are deciding between models in principle: see relational vs document database and SQL vs NoSQL.
Final recommendation
For relational data with evolving queries, MySQL remains the safer choice in our view, and on AWS Aurora MySQL (now with 8.4) or RDS removes most of the operations work. DynamoDB is the better fit when you are committed to AWS, the access patterns are known and key-based, and you want throughput that scales without servers or shards. If the only reason to move is write volume, evaluate Vitess or PlanetScale first: they keep SQL, at the cost of cross-shard rules, while DynamoDB requires redesigning the data around its keys.
Frequently asked questions
Can I migrate a MySQL database to DynamoDB?
Yes, with AWS DMS, which supports DynamoDB as a target and maps rows to items with object-mapping rules. Dates become strings, numbers are limited to 38 digits of precision, key attributes cannot be updated through CDC, and most LOBs are not supported. To benefit from DynamoDB you usually also redesign keys around access patterns.
Does DynamoDB support joins like MySQL?
No. Related items are usually stored under the same partition key and read together, or fetched with several requests. Reports that need joins or GROUP BY are usually run elsewhere, for example after the zero-ETL integration with Amazon Redshift.
How do I enforce a unique email in DynamoDB?
Only the primary key is unique. One approach is a transaction that writes the user item and a second item keyed on the email with an attribute_not_exists condition, kept in step whenever the email changes. In MySQL, a UNIQUE constraint does this.
Is Aurora MySQL an alternative to DynamoDB for scale?
For reads and moderate writes, often: an Aurora MySQL cluster can have up to 15 Aurora Replicas on a shared storage volume, and Aurora Serverless scales capacity automatically. Each cluster still has a single writer, and AWS's managed horizontally scaled relational options (Aurora PostgreSQL Limitless Database and Aurora DSQL) are PostgreSQL-only.
What is Vitess?
An Apache-2.0, CNCF-graduated system that shards MySQL across many instances behind a MySQL-compatible proxy. Applications keep SQL, but transactions across shards are best-effort by default and need the twopc mode for atomic commits. PlanetScale offers it as a managed service.
Sources
- Amazon DynamoDB Developer Guide: Time to Live
- Amazon DynamoDB Developer Guide: Zero-ETL integration with Amazon Redshift
- Amazon DynamoDB Developer Guide: PartiQL
- Amazon DynamoDB on-demand pricing
- AWS DMS User Guide: DynamoDB as a target
- AWS What's New: Amazon Aurora MySQL 8.4 is generally available
- Aurora MySQL release notes: 8.4.8
- Amazon Aurora User Guide: Replication with Aurora
- Amazon Aurora User Guide: Aurora PostgreSQL Limitless Database
- Vitess documentation: What is Vitess
- Vitess documentation: Distributed transactions
- Vitess GitHub repository (licence)
- PlanetScale pricing
- MySQL NDB Cluster
- MySQL 8.4 Reference Manual: INSERT ... ON DUPLICATE KEY UPDATE
Checked October 2026.
How we research comparisons: our editorial method.