Database parity — Cloud SQL, AlloyDB, Spanner, Firestore and Bigtable against the AWS and Azure catalogues
Counterpart names, including the two rows where no counterpart is honest, then the differences that change an estimate: the availability model behind a managed relational instance, Spanner's missing equivalent, the two things a Firestore application needs on the far side, and where a lift actually exists.
markdownguidev1JRKM-QZVVstage: designtrust: officialfamily: databasesservice: cloud-sqlinterface: anydatabase paritycloud SQLRDSAuroraazure SQLazure database for postgresqlalloydbspannercosmos dbfirestoredynamodbdocumentdbbigtableazure table storageHBasememorystoremanaged redis
Database parity
1. The names, with the two honest gaps marked
| Google Cloud | AWS | Azure |
|---|---|---|
| Cloud SQL (MySQL, PostgreSQL) | Amazon RDS, Aurora | Azure Database for MySQL flexible server, Azure Database for PostgreSQL |
| Cloud SQL (SQL Server) | RDS for SQL Server | the Azure SQL family: Azure SQL Database, Azure SQL Managed Instance, SQL Server on Azure VMs |
| AlloyDB | Aurora PostgreSQL | Azure Database for PostgreSQL (no exact tier match) |
| Spanner | Aurora, Aurora DSQL — no exact counterpart | Cosmos DB for NoSQL and Azure Database for PostgreSQL — Microsoft's own table gives two, which is the gap |
| Firestore | DocumentDB, DynamoDB | Cosmos DB |
| Firestore real-time updates | DynamoDB Streams (not equivalent) | Cosmos DB change feed |
| Bigtable | DynamoDB; EMR-hosted HBase for the ecosystem | Azure Table Storage (name match, not capability match) |
| Memorystore | ElastiCache | Azure Managed Redis |
Two rows deserve the warning they carry. Microsoft's table maps Spanner to two unrelated Azure services, and both tables map Bigtable to Table Storage — a product that is not a petabyte-scale HBase-ecosystem store. A name table is the right tool for finding a starting point and the wrong tool for sizing a migration. These two rows are where that shows most.
2. Managed relational — the availability model, not the engine, is the difference
| Google Cloud | AWS | Azure | |
|---|---|---|---|
| HA shape | a standby VM in another zone, within one region | Multi-AZ instance or Multi-AZ cluster | zone-redundant HA within a region |
| editions | Cloud SQL Enterprise and Enterprise Plus (PostgreSQL, MySQL) | RDS vs Aurora, plus instance classes | Flexible Server tiers; the Azure SQL family is three products |
| what a maintenance update costs | an instance restart, with downtime; Enterprise Plus can achieve "sub-second downtime" | a maintenance window with failover | a maintenance window |
| the credential-free path | IAM database authentication + a connector + roles/cloudsql.client | IAM authentication for RDS | Microsoft Entra authentication |
Three estimate-bearing readings.
- All three put managed relational HA inside one region. A cross-region requirement is a read replica, a
secondary, or a different product on every cloud — so a promise of "the same RPO" has to name the mechanism, not the service.
- The SQL Server row is one-to-three on Azure. Cloud SQL for SQL Server maps onto the Azure SQL family,
and which member you land on determines the compatibility surface: SQL Managed Instance is near-complete SQL Server, Azure SQL Database is not. Deciding that row is a workload-by-workload assessment, and it is usually the single largest unknown in a SQL Server migration either way.
- The maintenance-restart question is edition-shaped on Google Cloud. If the application cannot absorb a
restart, the answer is Enterprise Plus, and it belongs in the estimate as an edition line rather than as an operational risk.
3. Spanner has no like-for-like counterpart — say so in the estimate
Google Cloud's published configurations: regional (three read-write replicas across zones, 99.99%), dual-region and multi-region (both 99.999%, both Enterprise Plus, multi-region accepting writes in more than one location at higher write latency).
The combination — relational semantics, horizontal write scaling, and a published multi-region write capability — is not matched by a single service on either other cloud. Aurora DSQL and Cosmos DB each cover part of it. So:
- onto Spanner: a possible simplification for an application that currently shards manually, and an
application change otherwise.
- off Spanner: an architecture change, costed as one. Any estimate that lines Spanner up against a
counterpart and multiplies by instance count is wrong before it starts.
Also carry the edition fact: two of the three configurations require Enterprise Plus, so a later move from regional to multi-region is an edition change as well as a topology change.
4. Document and wide-column — where the lift exists, and where it does not
| The lift | The work | |
|---|---|---|
| Firestore native mode | MongoDB compatibility means a MongoDB-driver application has a path that is not a rewrite (native mode only, not Datastore mode) | its real-time updates and direct client libraries have no single counterpart — on the far side that is a change feed plus an API tier plus a new authorisation model. Two or three components, routinely missed |
| Bigtable | HBase ecosystem integration — an HBase application moves with a client-library change. The cleanest lift in this family | everything else is a data-model exercise: one index, the row key, no secondary indexes and no joins |
| Firestore Datastore mode | — | it exists for a dependency on the Datastore APIs. Nothing elsewhere has them; a move off is a rewrite of the data layer |
And one trap that is not a migration cost at all but presents as one. Bigtable is strongly consistent on
a single cluster and eventually consistent by default on multiple clusters. A team that adds a cluster for
availability during a migration changes the consistency model mid-move, and then attributes the resulting bugs
to the migration. Configure read-your-writes or strong consistency explicitly
(reference/databases/errors.md §5).
5. Pricing dimension (never a price)
| Google Cloud | AWS | Azure | |
|---|---|---|---|
| managed relational | instance size (vCPU/memory) + storage + backups + edition; network egress | instance class + storage + I/O (or Aurora's I/O-optional) + backups | vCPU + storage + backup, by tier |
| the Google-built relational | AlloyDB: nodes per instance, plus storage | Aurora: capacity + I/O or Aurora Serverless ACUs | — |
| horizontally scaling relational | Spanner: compute capacity in nodes / processing units, plus storage; configuration changes the replica count | Aurora DSQL: request units | Cosmos DB: request units + storage |
| document | Firestore: operations + storage + network | DynamoDB: RCU/WCU or on-demand requests + storage | Cosmos DB: RUs + storage |
| wide-column | Bigtable: nodes + storage on Colossus | DynamoDB: as above | Table Storage: transactions + storage |
The structural trap in this table: Google Cloud mostly meters provisioned capacity (nodes, processing
units, instance size) where DynamoDB and Cosmos DB meter request units. Those are not convertible without
a workload profile. A migration estimate that converts an RU/s figure into node count by ratio is guessing;
the only honest conversion runs through measured read/write volumes and item sizes.
guides/parity-and-migration-method.md treats that as a required input, not an optional one.
6. What this guide cannot tell you
Whether a given SQL dialect, extension or stored-procedure estate ports. On the relational side that is the
whole of the work and it is per schema. Use the migration family's assessment tooling
(reference/migration/database-migration-service.md) rather than a table.