Overview

Use Postgres by default; use DynamoDB when the workload is a known set of key-based access patterns at very large scale, on AWS, with no servers to run. DynamoDB makes you design tables around queries up front; Postgres lets you add an index later and join across tables. Aurora DSQL, a serverless distributed SQL service compatible with PostgreSQL 16, now covers some of DynamoDB’s multi-Region use cases with SQL.

Comparison

DimensionPostgres 18 (RDS or Aurora)DynamoDB
QueriesAny SQL; joins; ad-hocKey and index lookups; no joins; scans read everything
Secondary access pathsAdd indexes any timeUp to 20 GSIs by default and 5 LSIs per table; model each access pattern; the primary key cannot be changed after creation
SchemaDeclared; migrationsSchemaless items; your code owns evolution
TransactionsDefaultTransactWriteItems and TransactGetItems APIs
Scale-out writesVertical plus replicas; Citus for shardingHorizontal and managed; on-demand capacity defaults to 40,000 read and write request units per table (adjustable)
Multi-RegionAurora Global Database (single writer)Global tables: eventual consistency (MREC, last writer wins) or strong consistency (MRSC, three Regions, no transactions or TTL)
OperationsInstances, upgrades, vacuum, poolingNone; pay per request or provisioned capacity
Change eventsLogical replication, CDCDynamoDB Streams

Pick Postgres when

Pick Postgres for almost every application database.

  • Access patterns will change, or you need reporting, filters, and joins on the same data. See postgres-indexes.
  • Transactions across several tables are normal.
  • Full-text search, vectors, or geospatial data live beside relational rows.
  • You want portability off AWS.

Pick DynamoDB when

Pick DynamoDB when its model matches the workload.

  • Known key-based access: sessions, device or event logs keyed by id and time, per-entity state, shopping carts.
  • Spiky, serverless traffic and no connection pools: the HTTP API fits Lambda well.
  • Built-in TTL expiry and Streams feeding Lambda, Kinesis, or EventBridge.
  • Multi-Region active-active writes with global tables. Choose MREC for lower latency; MRSC for zero data loss but exactly three Regions and no transactions.
  • Use redis-vs-memcached when sub-millisecond reads on in-memory data matter more than durability.

Migrate

Neither direction is a data copy; both are a data model redesign. Postgres to DynamoDB: list every query, design partition and sort keys and GSIs per access pattern, and rewrite data access. DynamoDB to Postgres: export to S3, COPY in, then design a relational schema from the denormalized items. Often better: keep DynamoDB for the hot key path and feed Postgres from Streams for relational queries. See aurora-vs-rds-postgres for managed Postgres on AWS.

FAQ

Should I use DynamoDB or Postgres for a new app?

Use Postgres by default, since access patterns change and indexes can be added later. Use DynamoDB only for known key-based access at very large scale on AWS with no servers to run.

Can DynamoDB do joins?

No; DynamoDB serves key and index lookups, and scans read everything. Model each access pattern up front with partition keys, sort keys, and up to 20 GSIs per table by default.

Which DynamoDB global tables mode should I use?

Choose MREC for lower latency with eventual consistency and last writer wins. Choose MRSC for zero data loss, which requires exactly three Regions and drops transactions and TTL.

Can I migrate from DynamoDB to Postgres?

Yes, but it is a data model redesign: export to S3, COPY in, and design a relational schema from the denormalized items. Often better is keeping DynamoDB for the hot key path and feeding Postgres from Streams.