The same primitive, three providers
A mapping you can use to read a design written for another cloud — and, much more importantly, a record of where that mapping misleads. The services in a row are near-equivalents and never exact ones, so the fourth column is the one to read.
Reading a row across is the fast way to orient yourself and the fast way to be wrong. The differences below are not trivia: they change whether a design that assumes per-key ordering still works, whether a bad query can affect everybody else, whether a schema change breaks a stream or is silently absorbed, and where a row-level access policy is even expressible. Each of those has ended a migration.
Consistency guarantees, listing behaviour at scale, per-request pricing shape and the semantics of a "directory" all differ. None of them has a real rename, so every atomic-publish pattern is an accommodation of that — but which operations are atomic varies.
The architectural split is genuinely different: some separate storage from compute entirely and charge for bytes processed, others provision a cluster you size. That changes how you optimise, how you attribute cost, and what a bad query can do to everyone else.
Ordering is the big one. Kafka-family systems order per partition; Pub/Sub gives no ordering unless an ordering key is set; Kinesis orders per shard. A design that assumes per-key ordering is not portable between them without changing the design.
What is managed varies from "the cluster" to "the job". Autoscaling behaviour, storage connector maturity and how a failed node is handled differ enough to change job tuning, and a configuration that works on one is not a configuration on another.
Some are general task orchestrators and some are data-movement products with orchestration attached. That decides whether your transformation logic lives in the orchestrator — which it should not — and how a partial failure is expressed.
Some are primarily a technical schema registry that engines read at query time; others are primarily a governance and discovery surface for humans. Treating one as the other produces either an empty catalog or an engine that cannot find its tables.
Which sources are supported, whether DDL changes are captured or silently break the stream, and what happens on connector restart all differ. The snapshot-to-stream handover — the part most likely to lose or duplicate rows — is implemented differently by each.
The unit a policy attaches to differs — a bucket, a project, a resource group — and so does whether a data-level policy (row filter, column mask) lives in the identity system or in the warehouse. That decides whether access is governed in one place or two.