mysqlpostgresqldatabasecost-optimization

MySQL vs PostgreSQL on managed services: does the engine change the bill?

The per-hour rates for managed MySQL and PostgreSQL are nearly identical on every major cloud. The cost difference shows up somewhere else entirely: in how each engine uses storage, connections, and replication. Here is where it actually lands.

The C3X Team··7 min read

Quick answer

On RDS the list price is identical: db.m6g.large is $0.1565 per hour for both MySQL and PostgreSQL in us-east-1, about $114 per month, and storage is $0.115 per GB-month for both. The cost difference is behavioral, not tariff-based. PostgreSQL holds a process per connection (5 to 10 MB each) so connection-heavy apps need larger instances or a pooler; MySQL uses threads and tolerates more connections per GB. PostgreSQL's MVCC bloat and index bloat can add 20 to 40 percent to storage without disciplined autovacuum, while InnoDB's clustered index makes secondary indexes wider. Expect engine choice to move the bill by 10 to 30 percent through these second-order effects, not through the rate card.

A recurring question in architecture reviews: will we save money by picking MySQL over PostgreSQL, or the other way round? The rate cards say no. Every major managed service charges the same hourly rate for both engines on the same instance shape. The interesting answer is that the engines still produce different bills, because they consume the resources you are paying for in different ways.

The rate cards are identical

ServiceShapeMySQLPostgreSQL
RDS us-east-1db.m6g.large$0.1565/hr$0.1565/hr
RDS us-east-1db.r6g.xlarge$0.518/hr$0.518/hr
RDS us-east-1gp3 storage$0.115/GB-mo$0.115/GB-mo
Cloud SQL us-central1per vCPU-hour$0.0413$0.0413
Azure Flexible ServerGeneral Purpose D2ds_v4same tier ratesame tier rate

So if someone tells you MySQL is cheaper, ask which line they mean. There is one genuine tariff exception worth knowing: SQL Server and Oracle carry licence costs that dwarf both open-source engines, which is why migrations off them are usually the highest-value database cost project available. Between MySQL and PostgreSQL there is no licence line at all.

Where PostgreSQL costs more

The connection model is the big one. PostgreSQL forks a backend process per connection, consuming roughly 5 to 10 MB of resident memory each before work_mem allocations. An application opening 500 connections holds 2.5 to 5 GB purely in connection overhead. MySQL uses a thread-per-connection model with a much smaller footprint, commonly under 1 MB per idle thread, and thread pooling in some builds reduces it further. For a connection-heavy microservice fleet, this can be the difference between a 16 GB and a 32 GB instance, about $150 per month on RDS r-family shapes.

The second is bloat. PostgreSQL's MVCC writes a new row version on update and leaves the old one for autovacuum to reclaim. On a high-churn table with an undersized autovacuum configuration, table and index bloat of 20 to 40 percent is common and occasionally far worse. Since RDS storage is a ratchet that autoscales up and never down, bloat converts directly into permanent storage cost: 400 GB of bloat on a gp3 volume is $46 per month forever. MySQL's InnoDB uses undo logs and purges more aggressively by default, so it bloats less in the steady state, though it is not immune.

Where MySQL costs more

InnoDB stores rows in a clustered index keyed on the primary key, and every secondary index stores the full primary key as its pointer. With a UUID primary key (16 bytes, or 36 as a string if someone did that), every secondary index carries that weight per row. A table with 200 million rows and four secondary indexes pays for roughly 12.8 GB of primary key copies with a 16-byte key, and nearly 29 GB with a 36-character string key. PostgreSQL's heap-plus-index layout stores a 6-byte tuple identifier instead.

MySQL also lacks a native equivalent to PostgreSQL's partial and expression indexes in older versions, which in practice means broader indexes and more index storage for the same query patterns. And replication differences matter: PostgreSQL's physical streaming replication ships WAL, which is compact for update-heavy workloads, while MySQL row-based binlog replication can be substantially chattier, which shows up as cross-AZ transfer at $0.01 per GB in each direction.

A realistic net comparison

Workload shapeCheaper engineWhy
Many short-lived connections, no poolerMySQLThread model uses far less memory per connection
High update churn, weak maintenance disciplineMySQLLess bloat accumulation on ratcheting storage
Wide tables, many secondary indexes, UUID keysPostgreSQL6-byte tuple pointers instead of full PK copies
Complex analytical queriesPostgreSQLBetter planner means smaller instance for the same queries
JSON-heavy documentsPostgreSQLJSONB with GIN indexes avoids a second datastore

That last row is often the largest effect of all and it never appears in an engine comparison table. PostgreSQL's extension ecosystem, JSONB, full-text search, PostGIS, and vector search among them, regularly lets a team avoid standing up a separate search cluster or document store. Avoiding a $300 per month secondary datastore is worth more than any per-connection memory difference.

The honest recommendation

Do not pick an engine on cost. Pick it on team familiarity, feature fit, and operational maturity, then manage the cost consequences of whichever you chose: add a connection pooler if you run PostgreSQL at high connection counts, tune autovacuum aggressively on high-churn tables, and avoid random UUID primary keys on wide InnoDB tables. Those three actions capture most of the 10 to 30 percent that engine behaviour puts on the table.

Price the instance shape, storage, and replication topology from Terraform before you provision, so the connection-driven memory sizing is a decision rather than an incident. Compare shapes against the resource catalog, and see connection pooling economics for the PostgreSQL side.

FAQ

Does RDS charge more for PostgreSQL than MySQL?

No. The list rate is identical: db.m6g.large is $0.1565 per hour for both engines in us-east-1, db.r6g.xlarge is $0.518 per hour for both, and gp3 storage is $0.115 per GB-month either way. Cloud SQL and Azure Flexible Server follow the same pattern. Only commercial engines like SQL Server and Oracle carry licence premiums, which is why migrating off those is the higher-value cost project.

Why does PostgreSQL need a bigger instance for many connections?

PostgreSQL forks a backend process per connection, consuming roughly 5 to 10 MB of resident memory each before work_mem allocations. At 500 connections that is 2.5 to 5 GB of pure overhead. MySQL uses a thread-per-connection model commonly under 1 MB per idle thread. For a connection-heavy microservice fleet this can be the difference between a 16 GB and a 32 GB instance, about $150 per month on RDS r-family shapes.

How much does PostgreSQL bloat cost?

On high-churn tables with undersized autovacuum settings, table and index bloat of 20 to 40 percent is common. Because managed storage autoscales up and never down, that bloat becomes permanent cost: 400 GB of bloat on RDS gp3 is about $46 per month indefinitely, and reclaiming it requires a dump and restore into a fresh instance rather than a simple setting change.

Do UUID primary keys cost more on MySQL?

Yes, more than on PostgreSQL. InnoDB stores rows clustered on the primary key and every secondary index stores the full primary key as its pointer. A 200 million row table with four secondary indexes carries roughly 12.8 GB of primary key copies with a 16-byte UUID, and nearly 29 GB if stored as a 36-character string. PostgreSQL uses a 6-byte tuple identifier instead.

Which engine saves more money overall?

Neither reliably. MySQL tends to win on connection-heavy workloads and high-churn tables with weak maintenance discipline. PostgreSQL tends to win on wide tables with many secondary indexes, complex analytical queries, and JSON workloads where JSONB avoids standing up a separate document store or search cluster. That last effect, avoiding a second datastore worth a few hundred dollars a month, is usually the largest.

How does C3X help with database engine cost?

C3X prices the instance shape, storage allocation, and replication topology from Terraform before you provision, so connection-driven memory sizing and storage growth assumptions are visible in the pull request. Since the engines charge the same rate but consume resources differently, seeing the sized infrastructure costed in advance is more useful than comparing rate cards that are identical by definition.

What to do next

Size your database before the engine behaviour sizes it for you. C3X reads your Terraform and prices your resources against a live catalog. Start with the quickstart.

Try C3X on your own Terraform

Free and open source. No API key required. One command to install, one command to estimate.