Skip to main content
DynamoDB
AWS
DynamoDB
PostgreSQL
アーキテクチャ設計
技術選定
サーバーレス

DynamoDB vs RDS/Aurora: the differences, and when to choose DynamoDB (2026 edition)

The differences between DynamoDB and Amazon RDS/Aurora (PostgreSQL), and how to choose, with comparison tables checked against AWS documentation and four decision axes. Covers JOINs, consistency, limits and pricing models, what changed since 2024 (Aurora DSQL, Serverless v2 scaling to 0 ACUs), hybrid designs, and the cost of forcing NoSQL.

Published
Last updated
Updated
Reading time
23 min read
Author
友田 陽大
Share

"DynamoDB for now" — this one phrase can become technical debt half a year later. Conversely, "the DB is the familiar PostgreSQL" can be a design that gets stuck at scale time.

Data-layer selection is a one-time judgment that most strongly governs a system's lifespan. Application code can be rewritten, but the data model and DB engine cost orders of magnitude more to swap later. That's exactly why this should be decided not by fashion or preference but by axes derived from requirements.

This article answers the pre-order, pre-start decision of "NoSQL (DynamoDB) vs. RDB (Amazon RDS / Aurora PostgreSQL)" with a reusable framework. From my position of having designed and led the reliability layer of a serverless multi-tenant payment platform (Lambda + DynamoDB, maintaining 0 double charges in production operation), I write "where to lean toward DynamoDB and where to leave on the RDB" as a practical line.

Let me say the conclusion first. DynamoDB and an RDB are not competitors but tools with different fortes. And in many real systems, using them separately (a hybrid), not either/or, is the correct answer.

Specs and limits are cross-checked against the AWS documentation (re-checked on 2026-11-09, with the changes since 2024 added). Pricing varies by Region and over time, so always confirm the final figure on the official pricing page.


1. Conclusion: decide selection by "4 axes"

Decide DynamoDB or RDB by "it's fast," "it's cheap," or "it's serverless" and you'll almost always miss. What you should judge is the following 4 axes.

AxisQuestionDynamoDB favorableRDB (Aurora/PostgreSQL) favorable
How settled the access patterns areCan you enumerate the query shapes before starting?can be settled in advancefreely increase later / exploratory
ScaleWhat's the assumed read/write scale and growth?ultra-large, open-ended growthmid-to-large is enough
Query flexibility and consistencyDo you need JOIN, aggregation, ad-hoc search?key/index lookup sufficesJOIN, GROUP BY, analysis-centric
Operational burdenHow much manpower can you put into operation?operation-less is top prioritywant room for tuning

These 4 axes aren't independent and often interlock. For example, if "access patterns can be settled in advance, ultra-large-scale, key lookup suffices, and want operation-less" all align, it's DynamoDB's exclusive stage. Conversely, "queries freely increase later, JOIN and aggregation-centric" means RDB is the only choice.

And the AWS official clearly distinguishes the optimal workloads of the two.

RDBMS's optimal workload: ad-hoc queries, data warehouse, OLAP (online analytical processing). DynamoDB's optimal workload: web-scale applications including social networks, games, media sharing, IoT.

This is the starting point for everything. An RDB if you want to query and analyze ad-hoc, DynamoDB if you want to keep answering settled questions at ultra-large-scale and low latency. With this as the pivot, the details below.


I can take on the implementation from this article as an engagement

Data-layer architecture: ORM selection, schema design, and zero-downtime migration

2. What is DynamoDB (the official definition, precisely)

Before judging, grasp DynamoDB's true identity with the official definition. It's not the marketing "fast KVS" but an engine that gained unlimited scale in exchange for design constraints.

One official sentence summarizes it all.

Amazon DynamoDB is a serverless, fully managed, distributed NoSQL database with single-digit millisecond performance at any scale.

The properties to read from here:

  • Serverless: no server provisioning, patching, management, or operation. No version or maintenance window. On-demand mode bills per request with no capacity planning; in AWS's words, "if you are driving zero traffic to your table, then with on-demand, you are not charged for any throughput" (storage is still billed).
  • Fully managed: AWS takes on setup, high availability, hardware, security, backup, and monitoring. Usable for production workloads from the moment you create it.
  • NoSQL (key-value + document): supports both key-value and document models. Schemaless, where each item can have its own attributes other than the primary key.
  • No JOIN: the official states plainly, "Unlike relational databases, DynamoDB doesn't support a JOIN operator." It instead recommends denormalizing data.
  • Single-digit milliseconds × any scale: consistent single-digit milliseconds at 100 users or 100 million users. It intentionally omits inefficient features (like JOIN) for scale.

In other words, DynamoDB is a tool that "discarded JOIN and flexible ad-hoc queries in exchange for predictable low latency and unlimited scale." Whether you can accept this trade becomes the core of selection.

The details of DynamoDB's internals (tables, items, primary keys, GSI, idempotency, conditional writes) are summarized in the sister article complete DynamoDB single-table-design & production-reliability patterns guide. This article concentrates on the step before that — "whether to choose DynamoDB in the first place."


3. The essential difference between SQL (RDB) and NoSQL (DynamoDB)

The official "from SQL to NoSQL" comparison is the foundation of selection. Let me organize the difference between RDBMS and DynamoDB with the official table.

AspectRDBMS (Aurora/PostgreSQL, etc.)DynamoDB
Optimal workloadad-hoc queries, data warehouse, OLAPweb-scale (SNS, games, media, IoT)
Data modela normalized strict schema (tables, rows, columns, relations)schemaless. Only the primary key required, no constraint on non-key attributes. Handles structured / semi-structured (JSON)
Data accessSQL is standard. A rich toolsetSDK (object/document/low-level). select/insert/update/delete with PartiQL (SQL-compatible)
Performancestorage-optimized. Tuning queries, indexes, and table structure sways performancecompute-optimized. Performance is mainly a function of hardware and network latency, and implementation details are hidden
Scalebasically vertical scale (faster hardware). Distribution is possible but needs extra investment, and there are upper limits on file count/size, capping scalabilityhorizontal scale with a distributed cluster. Can increase throughput without raising latency. There's no upper limit on item count or total size per table

The difference in the official design philosophy is also decisive.

In RDBMS, data can be queried flexibly, but queries are relatively expensive and don't scale well in high-traffic situations. In a NoSQL database such as DynamoDB, data can be queried efficiently in a limited number of ways, outside of which queries can be expensive and slow.

This is the essence. An RDB is "flexible but clogs at high traffic," DynamoDB is "invincible at the settled lookup but bad at anything else." In one line —

  • RDB = design for flexibility (add queries later without worrying about implementation or performance. Normalization is important)
  • DynamoDB = design to make the most-frequent, most-important queries fastest and cheapest (build the data structure to fit the use case)

Hard differences: limits, transactions, consistency

Apart from what each engine is good at, some differences are simply numbers. Miss them and you find out later that the design you wanted isn't possible (AWS documentation, November 2026).

AspectDynamoDBRDS for PostgreSQL / Aurora PostgreSQL
Size limitsItems up to 400 KB (attribute names included). No practical limit on table sizeRDS for PostgreSQL storage up to 64 TiB (most instance classes). Aurora up to 256 TiB (PostgreSQL 17.5, 16.9, 15.13 and later; 128 TiB on earlier versions)
TransactionsTransactWriteItems / TransactGetItems: up to 100 items (actions) and 4 MB per callSQL transactions (BEGIN … COMMIT) can update several tables atomically
Read consistencyTables and LSIs offer eventually consistent (default) or strongly consistent reads. Reads from GSIs and streams are eventually consistent onlyReads from the writer are current; read replicas apply writes after the fact and can lag slightly
Indexes20 GSIs per table by default (raisable on request), up to 5 LSIsCREATE INDEX as needed; a new search condition usually means a new index, not a redesign
Multi-RegionGlobal tables. Multi-Region strong consistency (GA June 2025) needs exactly three Regions and does not support TTL, LSIs or transactionsAurora Global Database (out of scope here). For active-active multi-Region SQL, see Aurora DSQL below

The one that bites most often is GSI eventual consistency. Check "is this email already registered?" through a GSI and you may not see a write made a moment ago. A GSI cannot enforce uniqueness, so put the unique value in a primary key or guard it with a transaction condition.


4. Where DynamoDB "fits"

The more the following conditions align, the more powerful DynamoDB is.

(1) Access patterns can be settled in advance

The iron rule of DynamoDB design, and the point the official most strongly admonishes.

you shouldn't start designing your schema for DynamoDB until you know the questions it will need to answer.

An RDB can "normalize first and add queries later," but DynamoDB is the reverse. It's premised on being able to enumerate the query shapes (access patterns) before starting. If the requirements are stable and you can assert "this system, after all, only looks up this and this," DynamoDB keeps answering those questions at minimal cost.

(2) Ultra-large-scale, open-ended growth is expected

The quotas page puts it this way: "There is no practical limit on a table's size. Tables are unconstrained in terms of the number of items or the number of bytes." According to the developer guide, hundreds of customers have tables with peak traffic of over half a million requests per second, and hundreds have tables larger than 200 TB.

For services where "if it succeeds, it may scale all at once" or "the peak is unreadable," you can avoid the RDB's vertical-scale ceiling and designing and running your own sharding (the RDB side now has managed sharding too: Aurora PostgreSQL Limitless Database, GA October 2024).

(3) Predictable low latency is needed

Single-digit milliseconds at 100 users or 100 million users. The design that doesn't slow down with scale works for "should always be fast" workloads like a game leaderboard, cart, session, or IoT telemetry.

(4) Want to prioritize serverless / operation-less

It natively integrates with Lambda, API Gateway, and AppSync, and you can build an event-driven architecture with zero server management. In on-demand mode, capacity planning is also unnecessary, and with no traffic there is no throughput charge (storage is still billed). It's the first candidate when a small team / solo developer wants to minimize operational burden.

(5) Key-value / document access suffices

If access is centered on lookups that suffice with a key (and limited indexes) — like "look up a profile by user ID," "fetch an order and its line items together by order ID" — the absence of JOIN isn't a constraint. With a design that cohabits related data (single-table design), you can replace JOIN-equivalents with key design.

My real example: areas like the payment core's "idempotency, balance, ledger," where access patterns are settled, consistency is most important, and it must endure ultra-large-scale, I leaned toward DynamoDB. Because you can "guarantee correctness by design" with conditional writes and transactions. For details, the payment-reliability case study.


5. Where an RDB (Aurora/PostgreSQL) "fits"

Conversely, if even one of the following strongly applies, you should straightforwardly choose an RDB. Posturing and going NoSQL here is the most common failure.

(1) Ad-hoc flexible queries are needed

"I want to search by a condition I thought of later," "the analysis axis changes frequently" — as the official names "ad-hoc queries" the RDBMS's optimal workload, this is RDB's exclusive stage. Against DynamoDB needing a GSI addition or data redesign every time a new lookup increases, an RDB just changes the WHERE clause.

(2) JOIN and relational integrity are central

If the worldview of normalizing multiple entities as relations, keeping integrity with foreign keys, and joining with JOIN is central, DynamoDB's denormalization / no-JOIN is too costly to fight. If a normalized relational model is the essence of the requirement, an RDB is the correct answer.

(3) Aggregation, analysis, reporting (OLAP)

GROUP BY, window functions, complex aggregation, BI reports. The area the official positions RDBMS as optimal for, "data warehouse / OLAP." Try this in DynamoDB and you end up relying on Scan (a full-table scan, high-cost), and the design collapses.

(4) Access patterns aren't settled yet / increase later

A startup's early stage, a PoC, a product with fluid requirements. At the stage where "what to look up" can't be settled before starting, an RDB's "build first, add later" flexibility wins decisively in development speed. Too-early DynamoDB adoption tends to become a self-harm of redoing the key design every time the spec changes.

The practical design (RLS, real-time, Edge Functions) when choosing an RDB (PostgreSQL/Supabase) in production is summarized in the Supabase production-operations guide. If you choose an RDB, this is the concrete implementation guideline.

Notes on Amazon RDS and Aurora

When choosing an RDB, the options on AWS are mainly Amazon RDS for PostgreSQL and Amazon Aurora PostgreSQL. Since this article's theme is the NoSQL vs. RDB axis, I won't dig deep, but roughly —

  • RDS for PostgreSQL: standard managed PostgreSQL. Simple and straightforward. Cost-efficient, and this is often enough to start.
  • Aurora PostgreSQL: PostgreSQL-compatible, with auto-expanding storage (up to 256 TiB on supported versions) and strong elastic scale via read replicas and Serverless v2. The higher-tier option when you want to extend scale while staying an RDB. If you need to spread writes across several writers (sharding), Aurora PostgreSQL Limitless Database has been generally available since October 2024.

If "an RDB but I also want scale," the right order is to first consider Aurora (Serverless v2 if needed), and carve out only the ultra-large-scale, specific-access-pattern parts that still aren't enough to DynamoDB.


6. Decision flowchart

Step through the axes in order and most cases can be judged mechanically. Evaluate from the top in order.

  1. Is the use centered on aggregation, analysis, ad-hoc search? → If YES, RDB (Aurora/PostgreSQL). (Official: OLAP, data warehouse is RDBMS's optimal area)
  2. Can you enumerate and settle the access patterns before starting? → If NO (freely increase later / exploratory), RDB. Re-evaluate after requirements settle.
  3. Are JOIN and complex relational integrity the essence of the requirement? → If YES, RDB. If you need SQL and JOINs but also want serverless writes in several Regions, Aurora DSQL is a candidate too (if you can accept optimistic-concurrency retries and the 3,000-row-per-transaction cap; see the addendum).
  4. Is the assumed scale enough with an RDB (Aurora)? → If YES (fits in mid-to-large scale), don't push it, RDB. Take the productivity of the familiar tool.
  5. Is the requirement ultra-large-scale, predictable low latency, serverless operation-less, and key-lookup-centric? → If YES, DynamoDB.
  6. Is it a consistency-critical core (payment, inventory, ledger) with settled access patterns? → If YES, DynamoDB (guarantee correctness with conditional writes and transactions).
  7. Is the core DynamoDB-suited but you also separately need analysis and flexible search? → If YES, hybrid (next chapter). Divide roles: core in DynamoDB, analysis in Aurora.

When in doubt, there are 2 principles. "An RDB if you want to query ad-hoc," "DynamoDB if you want to answer settled questions at ultra-large-scale." And the more you're unsure, the less settled the requirements are, so start with an RDB first is safe. Because RDB → partial DynamoDB-ization is realistic, but the reverse (full DynamoDB adoption → after all, ad-hoc analysis is needed) is very painful.


7. Hybrid configuration: don't make it either/or

Many real systems strain if you try to cover everything with one engine. The correct design is to divide roles to the optimal engine per use.

Pattern A: division by use (core vs. analysis/search)

  • A core needing transaction consistency (payment, inventory, counter, ledger) → DynamoDB. Settled access patterns at low latency and unlimited scale.
  • Ad-hoc analysis, reports, complex search → Aurora PostgreSQL (or an analysis foundation). With flexible SQL.

My design on the payment foundation was also this division. Consistency-critical writes "guarantee correctness by structure" in DynamoDB, and areas needing exploratory queries escape to a separate engine. Using each tool only in its forte is, after all, the fastest, cheapest, and safest.

Pattern B: escape only analysis to a separate engine with Zero-ETL

If you want analysis while placing DynamoDB at the core, you don't need to ETL the data by hand. The official provides managed integrations.

  • Zero-ETL integration (Amazon Redshift): link DynamoDB's data to Redshift without affecting the production workload and run complex analysis.
  • Zero-ETL integration (OpenSearch Ingestion): run full-text search, vector search, and semantic search against DynamoDB data.
  • S3 export → Athena/Glue: export to S3 with full/incremental export and do ad-hoc analysis with Athena. You can analyze all records without directly Scanning the production table.

The point is that these don't affect the production DynamoDB workload. You can realize "OLTP in DynamoDB, OLAP in a separate engine" without increasing operational burden.

Pattern C: real-time linkage with DynamoDB Streams

DynamoDB Streams captures item creation, update, and deletion in a near-real-time time series. Connect this to a Lambda trigger and you can asynchronously reflect writes as events to other systems (a search index, an aggregation table, an RDB read model). It becomes the foundation of a CQRS-like division of writes in DynamoDB, derived views elsewhere.


8. The cost view: which is cheaper is decided by the "shape"

There's no uniform answer to "DynamoDB or RDS, which is cheaper?" Because the billing models are fundamentally different.

AspectDynamoDBRDB (Aurora/PostgreSQL)
Billing unitrequests (on-demand) or reserved capacity (provisioned) + storagemainly instance uptime (+ storage, I/O. Aurora Serverless v2 is metered by capacity)
At zero trafficon-demand charges nothing for throughput (storage is still billed)provisioned instance billing keeps running. Serverless v2 with a 0-ACU minimum has no instance charge while paused (resume takes about 15 s, 30 s or more after a pause of over 24 hours; never pauses with RDS Proxy attached)
Spike handlingon-demand absorbs it instantlyscaling needs time and design
Many flexible queriesrisk of cost ballooning with heavy Scanefficient with SQL, but clogs at high traffic
Free tieralways-free tier (25 GB storage + 25 RCUs / 25 WCUs; "enough for about 200M requests/month (depending on item size)," per AWS)new accounts get credits (up to $200; the Free plan ends after 6 months, on a Paid plan they last up to 12 months); check the pricing page for terms

The rough tendency:

  • Traffic is intermittent, spiky, unreadable → DynamoDB (on-demand) is cost-efficient. Pay for what you use. On the RDB side, Aurora Serverless v2 at 0 ACUs is a candidate if you can live with the resume delay.
  • A constant load keeps running → RDB's instance billing works straightforwardly. DynamoDB can counter with provisioned + reserved, but since the November 2024 price cut it is safer to measure on on-demand first and switch only if the numbers say so (AWS calls on-demand its default and recommended mode).
  • Beware hidden costs: DynamoDB has "counting traps" like billing for Scan, FilterExpression, condition failures, and UpdateItem. Force ad-hoc analysis in DynamoDB and the cost balloons. For details, the capacity, cost, performance design guide.

Don't choose the engine by cost alone. Using the correct engine correctly is always cheaper in total cost (development, operation, rebuild at scale time) than running the wrong engine cheaply.


Addendum: what changed in 2024–2026

A few changes make older comparisons misleading. Each one below is checked against an AWS announcement and the documentation.

Aurora DSQL: serverless, multi-Region SQL (GA May 2025)

AWS describes Aurora DSQL as a "serverless, distributed SQL database with active-active high availability and multi-Region strong consistency." It is PostgreSQL-compatible, and the easiest way to place it is as a new option between DynamoDB and Aurora.

It is not a drop-in PostgreSQL, though:

  • Optimistic concurrency control (OCC): instead of making transactions wait on locks, it fails the conflicting one at commit. The application has to be designed to retry.
  • Transaction limits: a transaction can change at most 3,000 rows and 10 MiB, and run for at most 5 minutes. Large batch updates must be split.
  • Not available: temporary tables, procedural languages such as PL/pgSQL, and triggers. Trigger logic moves to the application or to event-driven services such as EventBridge; procedural logic moves to the application or to Lambda.
  • Transaction behaviour: the isolation level is fixed at Repeatable Read, and DDL and DML must run in separate transactions.
  • Added later: sequences and identity columns arrived in February 2026, foreign key constraints in August 2026. Older comparisons saying "no foreign keys" are out of date.

How to choose: if you can't give up SQL and JOINs but don't want to run servers and need writes in several Regions, look at Aurora DSQL. If your reads are settled key lookups and predictable low latency comes first, DynamoDB fits better, without DSQL's retries and transaction caps.

Aurora Serverless v2 scales to 0 ACUs (November 2024)

Serverless v2 used to bottom out at 0.5 ACUs, so idle hours still cost money. Now, with a minimum capacity of 0 ACUs, it pauses automatically when there are no connections, and the instance charge while paused is zero (storage and other cluster charges remain). AWS's caveat is that resuming takes about 15 seconds, and it recommends client timeouts longer than that. It needs Aurora PostgreSQL 16.3, 15.7, 14.12, 13.15 or later (among others).

There are conditions. An instance paused for more than 24 hours can drop into a deeper sleep and take 30 seconds or more to resume. A cluster with an RDS Proxy attached (a common setup for Lambda) never pauses, because the proxy keeps a connection open. The writer also stays up in a cluster with logical replication enabled, in the primary cluster of an Aurora Global Database, and in a cluster with a zero-ETL integration to Redshift.

For development environments or internal systems that sit idle at night and avoid those setups, the "an RDB bills even when nobody uses it" gap with DynamoDB has narrowed.

DynamoDB on-demand got 50% cheaper (November 2024)

From November 1, 2024, on-demand throughput prices fell by 50%. Replicated writes for global tables fell by 67% on on-demand tables and 33% on provisioned ones. If your estimate assumes on-demand is the expensive option, rerun it against the current pricing page. The always-free tier (25 GB of storage, 25 WCUs and 25 RCUs — "enough for about 200M requests/month (depending on item size)," per AWS) is still offered, separately from the credits for new accounts (up to $200; the Free plan ends after 6 months, and on a Paid plan the credits last up to 12 months).

Strong consistency for DynamoDB global tables (GA June 2025)

Global tables used to mean eventual consistency; now multi-Region strong consistency (MRSC) is an option. It is fixed at exactly three Regions (three replicas, or two replicas plus a witness), does not support TTL, LSIs or transactions, and only an empty table can be converted. Check that these constraints fit your design before treating it as the answer.


9. Antipattern: forcing DynamoDB when an RDB is the correct answer

The most common and most costly failure is choosing DynamoDB "because it's cool / serverless" and shoving RDB-suited requirements into it. Typical symptoms:

  • Proliferating GSIs: adding a GSI for every new query, approaching the default quota (20 GSIs per table). It wastes write cost and quota, and the design collapses.
  • Scan hell: implementing ad-hoc filtering with Scan + FilterExpression. A filter only narrows after reading, and billing is for all records read. A full-table scan sits on the production hot path.
  • Re-implementing JOIN on the app side: looking up multiple tables and merging in the app. It's just hand-rewriting the RDB's JOIN, and both integrity and performance degrade.
  • Full scan for aggregation: implementing a GROUP BY-equivalent with a full read, and cost and latency explode.
  • Key redesign every time the requirement moves: adopting it at a stage where access patterns aren't settled, and redoing the data model every spec change.

These are all signs of forcing "what DynamoDB is bad at." If even one applies, that use (at least that part) should be returned to an RDB.

There's a failure in the reverse direction too. The case of needing ultra-large-scale and predictable low latency on an RDB, but burning out on your own sharding or homemade scale measures. A core with settled access patterns needing open-ended scale should be carved out to DynamoDB.

To put it critically — "all DynamoDB" and "all RDB" are usually thought-stopping. Judge by axes per use, and hybrid if needed. This is the selection that doesn't produce technical debt.


10. Migration pitfalls

"Just change the engine later" costs far more than you imagine. You should factor migration cost into the selection.

  • RDB → DynamoDB is "a data-model redesign": not a mere data transfer. You need to re-denormalize the normalized relational model from settled access patterns. If you can't translate the queries the JOIN was covering into key design, the migration fails. Inventory the access patterns first, then start.
  • DynamoDB → RDB is "restoring lost relationships": re-normalizing the data scattered by denormalization is laborious. That's exactly why the first selection matters.
  • Verify that access patterns are truly settled: before leaning toward DynamoDB, sternly ask "won't new lookups increase in the next 1-2 years?" If they will, leave that part on an RDB or make it hybrid.
  • Non-stop migration needs design: to evolve the data layer without stopping production, the standard is a staged migration of dual write (mirror write) → backfill → read switch → old removal (detailed in the single-table-design guide). I updated the payment foundation with this method without stopping for even one second.

A selection that doesn't premise migration is best. Choose correctly by axes at the start, and absorb the changeable parts with a hybrid, and you can avoid the big migration itself.


11. Selection checklist (verbalize in code)

Verbalize the judgment axes in a reviewable form and consensus-building with the team/client becomes faster. Here's an example of leaving "the basis of the decision" as a TypeScript type.

/** データ層選定の判断材料。各フラグは「設計レビューで合意した事実」を表す。 */
type DataLayerDecisionInput = {
  /** 着手前にアクセスパターンを列挙して確定できるか */
  accessPatternsKnownUpfront: boolean;
  /** JOIN・複雑な関係整合性が要件の本質か */
  needsJoinsAndRelations: boolean;
  /** 集計・分析・アドホック検索(OLAP)が中心か */
  needsAdHocAnalytics: boolean;
  /** Aurora で収まらない超大規模・青天井の成長が見込まれるか */
  needsHyperScale: boolean;
  /** サーバーレス・運用レスを最優先するか */
  prioritizeServerlessOps: boolean;
};

type Recommendation = "DynamoDB" | "RDB(Aurora/PostgreSQL)" | "Hybrid";

/**
 * 公式の最適ワークロード(RDBMS=アドホック/OLAP, DynamoDB=Webスケール)に基づく素朴な判定。
 * 注: これは思考の補助線であって、最終判断は要件全体の重み付けで行う。
 */
function recommendDataLayer(i: DataLayerDecisionInput): Recommendation {
  // RDBが本質的に必要な要件は、まずRDBを基軸にする
  const rdbCore = i.needsJoinsAndRelations || !i.accessPatternsKnownUpfront;
  // DynamoDBが強く効く要件
  const ddbCore =
    i.accessPatternsKnownUpfront && i.needsHyperScale && i.prioritizeServerlessOps;

  // コアはDynamoDB向きだが、分析・柔軟検索も要る → 役割分割
  if (ddbCore && i.needsAdHocAnalytics) return "Hybrid";
  if (rdbCore && i.needsHyperScale) return "Hybrid";
  if (ddbCore) return "DynamoDB";
  return "RDB(Aurora/PostgreSQL)";
}

This decision covers only the NoSQL-vs-RDB axis and deliberately leaves out in-between options such as Aurora DSQL. This code is not "a device that auto-generates the correct answer" but a checklist to make the basis of the judgment explicit and prevent oversights. It can visualize a contradiction like trying to choose DynamoDB alone while needsAdHocAnalytics is true.


Closing: choose the tool by axes

DynamoDB and Amazon RDS/Aurora (PostgreSQL) are not superior/inferior but tools with different fortes.

  • DynamoDB: a key-lookup-centric workload where access patterns are settled and ultra-large-scale, predictable low latency, and serverless operation-less are needed.
  • RDB (Aurora/PostgreSQL): a requirement centered on ad-hoc flexible queries, JOIN, and aggregate analysis (OLAP), where queries freely increase later.
  • Hybrid: core in DynamoDB, analysis/search to Aurora or Redshift/OpenSearch. The optimal answer for many real systems.

Since the official clearly divides the two's optimal workloads into "ad-hoc/OLAP" vs. "web-scale," the answer to selection is within the requirements. Decide by axes — access pattern, scale, consistency, query flexibility, operational burden — not fashion. With just this, most of the technical debt half a year later can be avoided.

In a structure of one person × generative AI (Claude Code), I've been thorough about a way of proceeding where design judgments pass through a human verification gate, and have designed and operated production systems that use DynamoDB and an RDB separately according to requirements. I can accompany you from the pre-order decision of "which is the correct answer for this workload of ours" through hybrid-configuration design and non-stop migration.

If you're troubled by data-layer technology selection, consult via contact. I start by inventorying the access patterns and consistency requirements together and designing the optimal combination of engines.

Frequently asked questions

DynamoDB or RDS, which is cheaper in the end?
It's decided by the workload's shape, and there's no uniform answer. If traffic is intermittent, spiky, unpredictable, DynamoDB (on-demand charges nothing for throughput when there is no traffic) is cost-efficient. For a constant load, an RDB's instance billing works straightforwardly, but DynamoDB can counter with provisioned + reserved. However, force ad-hoc analysis in DynamoDB and Scan billing balloons the cost, so not choosing the engine by cheapness alone ends up cheapest.
Can you do JOIN in DynamoDB?
You can't. As the official states plainly, DynamoDB doesn't support a JOIN operator. Instead, realize JOIN-equivalents with data denormalization and a design that cohabits related data on the same key. If JOIN and relational integrity are the essence of the requirement, you should straightforwardly choose an RDB (Aurora/PostgreSQL).
What happens if access patterns increase later?
In DynamoDB, every new lookup tends to need a GSI addition or data redesign (GSIs default to 20 per table). So being able to settle access patterns before starting is a premise of DynamoDB adoption. If lookups will freely increase in the next 1-2 years is expected, leave that part on an RDB or make it hybrid. An RDB handles a new query just by changing the WHERE clause.
What apps does DynamoDB fit?
The official lists web-scale apps — social networks, games, media sharing, IoT — as the optimal workload. Concretely, cases where access patterns can be settled in advance, ultra-large-scale and predictable low latency are needed, lookups are key-centric, and you want serverless operation-less. A cart, session, leaderboard, telemetry, and a consistency-critical core like payment, inventory, or ledger are good examples.
I want analysis but want to use DynamoDB. Can I have both?
You can. The standard is a hybrid that places the core in DynamoDB and escapes analysis to a separate engine. With Zero-ETL integration, you can link to Redshift (analysis) or OpenSearch (full-text/vector/semantic search) without affecting the production workload, and with S3 export → Athena, you can analyze all records too. You can realize OLTP in DynamoDB, OLAP in a separate engine without increasing operational burden.
In one sentence, how do DynamoDB and Aurora (RDS) differ?
DynamoDB has you decide how the data will be read up front and then serves exactly those reads fast and cheaply at any scale; Aurora/RDS lets you ask new questions in SQL later. DynamoDB has no JOINs, items are capped at 400 KB, a transaction holds at most 100 actions and 4 MB, and reads from a GSI are eventually consistent only. Aurora/RDS gives you JOINs, aggregation and ad-hoc queries, but scales mainly by instance, and RDS for PostgreSQL storage tops out at 64 TiB on most instance classes.
When in doubt, which should I start with?
If requirements aren't settled, start with an RDB first is safe. An RDB has the flexibility to add queries later, and RDB → partial DynamoDB-ization is realistic. Conversely, after full DynamoDB adoption, after all, ad-hoc analysis is needed is very painful. I recommend the order of carving out only the parts where access patterns are settled and ultra-large-scale, low latency, and operation-less are needed, to DynamoDB.
Aurora DSQL or DynamoDB — which should I pick?
If you want to keep SQL (PostgreSQL-compatible) and JOINs while getting serverless operation and multi-Region strong consistency, Aurora DSQL is a candidate (generally available since May 2025). It uses optimistic concurrency control, so a conflicting transaction fails at commit and the application has to retry. A transaction can change at most 3,000 rows and 10 MiB and run for 5 minutes, and temporary tables and PL/pgSQL are not available. If your reads are settled key lookups and predictable low latency matters most, DynamoDB fits better, without DSQL's retries and transaction caps.

References

友田

友田 陽大

Developer of a METI Minister's Award–winning product. With TypeScript + Python + AWS, I deliver SaaS, industry DX, and production-grade generative AI (RAG) end to end — from requirements to infrastructure and operations — single-handedly.

I can take on the implementation from this article as an engagement

Data-layer architecture: ORM selection, schema design, and zero-downtime migration

The real question is not which ORM you pick — it is whether the data model survives five years of change. I handle the selection (Prisma / Drizzle / SQLAlchemy), where to normalise and where not to, N+1 and connection-pool design, and schema migrations that never take the service down. Having led the reliability layer of a payment platform — designing the idempotency and consistency that kept production double-charges at zero — I build data layers that fail loudly and roll back cleanly.

Available for both project-based (contract) and advisory engagements. Start with a free 30-minute consult.

Also worth reading