Storage & Data¶
Every choice on this page answers the same two questions for a different shape of data: how many things need to read or write it at once, and how fast does a copy of it need to exist somewhere else to be safe. Object, block, and shared-file storage split on the first question; Multi-AZ, a read replica, and Multi-Region split on the second — and the reason a Multi-AZ failover is instant while a read-replica promotion is a deliberate manual step comes down to one word: synchronous vs asynchronous.
Scope: the AWS module page introduced the S3/EBS/EFS storage table, the Multi-AZ-vs-read-replica resilience split, and the DynamoDB-vs-RDS/Aurora database table. This page goes one layer deeper on each: the storage-class and volume-type choices inside each storage service, the mechanics that make Multi-AZ and a read replica behave differently, and what actually changes when you pick DynamoDB over RDS/Aurora.
TL;DR — in 30 seconds:
- S3/EBS/EFS split by access pattern, not just scope: S3 for whole files over HTTP (no server to manage), EBS for one attacher needing low-latency block storage, EFS only when multiple instances/Pods need the same files at once.
- Multi-AZ is a synchronous standby that fails over automatically (protects against an AZ dying); a read replica is asynchronous and exists for read-scaling, not resilience — promoting one is a manual, deliberate action.
- DynamoDB trades joins/schema for near-unlimited horizontal scale at known-key-lookup latency; RDS/ Aurora keep full SQL and joins, with Aurora decoupling storage scaling from compute and replicating synchronously across AZs at the storage layer.
1. Object vs block vs file — the same table, one layer deeper¶
The module page's storage table sorted S3/EBS/EFS by scope and attachments. The decision a team actually makes is driven by access pattern, not just those properties:
flowchart TD
Q{"What does the workload need?"}
Q -->|"store/retrieve whole files over HTTP,<br/>any number of clients, no filesystem needed"| S3["S3 — object storage"]
Q -->|"a filesystem one instance/Pod<br/>reads and writes as a disk"| EBS["EBS — block storage"]
Q -->|"a filesystem many instances/Pods<br/>need to read and write at once"| EFS["EFS — shared file storage"]
- S3 is reached for first for anything that's fundamentally a file to fetch — static assets, backups, data-lake input, build artifacts — because it has no server to manage and scales without a capacity decision.
- EBS is reached for when the workload expects a real filesystem with low, consistent latency and only one attacher at a time — a database's data directory is the canonical case.
- EFS is reached for only when more than one instance/Pod must see the same files at once — shared config, shared uploads, a build cache several CI runners hit in parallel.
2. S3 storage classes and lifecycle rules¶
S3's eleven nines of durability (from the module page) is the same across every storage class — what changes between classes is retrieval speed vs cost, not durability:
| Class | Access pattern | Trade-off |
|---|---|---|
| Standard | frequently accessed | highest storage cost, no retrieval delay |
| Standard-IA / One Zone-IA | accessed occasionally, still needed fast when accessed | lower storage cost; a per-GB retrieval fee; One Zone drops the multi-AZ redundancy for a further discount |
| Glacier (Instant / Flexible / Deep Archive) | rarely accessed, archival | lowest storage cost, in exchange for a retrieval delay that grows the cheaper the tier gets |
A lifecycle rule automates the move down this table on a schedule — "after 30 days move to Standard-IA, after 90 days move to Glacier" — so the storage-class decision doesn't have to be made once and then re-made manually as data ages.
3. EBS volume types¶
Underneath "EBS is block storage" is a choice between SSD- and HDD-backed volumes, matched to the I/O shape the attached workload actually produces:
| Type | Backing | Best for |
|---|---|---|
| gp3 (General Purpose SSD) | SSD | the default reach-for — balanced price/performance, IOPS and throughput configurable independently of size |
| io2 (Provisioned IOPS SSD) | SSD | latency-sensitive, high-IOPS workloads (large relational databases) that need a guaranteed floor |
| st1 (Throughput Optimized HDD) | HDD | large, sequential-read workloads (big data, log processing) where throughput matters more than IOPS |
| sc1 (Cold HDD) | HDD | infrequently accessed data where cost per GB matters most |
An EBS snapshot is a point-in-time, incremental backup of a volume — only the blocks that changed since the last snapshot are stored, which is why frequent snapshots stay cheap even on a large volume.
4. EFS throughput and lifecycle¶
EFS carries its own two-axis choice, separate from the S3/EBS decisions above:
- Throughput mode — Bursting scales throughput with the filesystem's size and is the default reach-for; Provisioned is chosen when a workload needs more throughput than its current size would earn under bursting.
- Storage classes — EFS mirrors S3's Standard-vs-IA idea: an EFS lifecycle policy automatically moves files that haven't been accessed in N days to the IA storage class, then back to Standard the moment they're accessed again — cheaper cold storage without giving up the shared-filesystem model.
5. DynamoDB vs RDS/Aurora — one layer deeper¶
The module page's table drew the line at "trades joins and schema" vs "MySQL/PostgreSQL-compatible." What that trade actually looks like day to day:
flowchart TD
Q{"What's the access pattern?"}
Q -->|"known key lookups at very large scale,<br/>no need for joins/arbitrary queries"| DDB["DynamoDB"]
Q -->|"existing relational workload,<br/>moderate scale"| RDS["RDS"]
Q -->|"relational workload that has outgrown<br/>a single RDS instance's storage/replication story"| AURORA["Aurora"]
| DynamoDB | RDS | Aurora | |
|---|---|---|---|
| Schema | schemaless beyond the key | fixed, relational | fixed, relational |
| Query model | primary key (partition key [+ sort key]) and indexes (GSI/LSI) — no arbitrary joins | full SQL, joins, transactions | full SQL, joins, transactions |
| Scaling | scales horizontally with no manual capacity planning; on-demand or provisioned capacity modes | scales vertically (bigger instance) plus read replicas | storage scales automatically and is decoupled from compute; compute still scales vertically (or via Aurora Serverless) |
| Reach for when | access pattern is known key lookups at very large scale | an existing relational workload, moderate scale | a relational workload that has outgrown a single RDS instance's storage/replication story |
Aurora's "storage-and-replication upgrade to RDS" (module page) is a specific architecture: writes are replicated synchronously across multiple Availability Zones at the storage layer itself, not by the database engine — which is why an Aurora failover is typically faster than a standard RDS Multi-AZ failover, and why Aurora can support more read replicas than RDS without adding replication lag to the primary. (Go deeper: the official Aurora storage and reliability overview — optional, not required to defend this page.)
6. Multi-AZ, read replica, Multi-Region — the mechanics behind the module-page rule¶
The module page's rule — Multi-AZ is for failover, a read replica is for read-scaling — comes from two different replication mechanisms:
| Multi-AZ standby | Read replica | Multi-Region | |
|---|---|---|---|
| Replication | synchronous | asynchronous | asynchronous (or Aurora's purpose-built cross-region replication) |
| Serves read traffic? | no | yes | yes, in its own region |
| Failover | automatic | not automatic — must be manually promoted | manual promotion, or purpose-built cross-region failover for the engines that support it |
| Protects against | a single AZ failing | nothing by itself (same region) — it exists for scale, not resilience | a whole region becoming unavailable |
Because the Multi-AZ standby is a synchronous copy, it can be promoted automatically the moment the primary is unreachable with no data loss. A read replica is asynchronous specifically so it doesn't add write latency to the primary — the cost of that speed is that it can lag behind, which is why promoting one is a manual, deliberate action rather than an automatic failover. How to weigh that trade-off in an actual DR plan — RTO, RPO, and which of these patterns fits a given recovery target — is the resilience module's territory, not repeated here.
7. How this connects¶
- This extends the AWS module page's Data theme (S3/EBS/EFS table, Multi-AZ-vs-read-replica rule, DynamoDB-vs-RDS/Aurora table) with the storage-class/volume-type choices inside each service and the replication mechanics behind the resilience rule.
- The Prove gate's DynamoDB/RDS/Aurora question draws directly on §5's table; the Multi-AZ RDS rollback scenario draws on §6's synchronous-vs-asynchronous distinction.
Common gotchas
- Treating a read replica as a DR mechanism. Fix: it's asynchronous and exists for read-scaling — it can lag behind and its promotion is manual, so it protects against nothing by itself; Multi-AZ (synchronous, automatic failover) is the resilience tool.
- Picking EFS by default for "shared storage" without a real multi-writer need. Fix: EFS earns its keep only when more than one instance/Pod must read/write the same files at once — a single attacher with a real filesystem is EBS's job, and EBS's low, consistent latency beats EFS there.
- Assuming all S3 storage classes differ in durability. Fix: eleven-nines durability is the same across every class — what changes is retrieval speed vs cost, not durability; pick a class (or a lifecycle rule) on access pattern, not "how important is this data."
- Forgetting DynamoDB has no arbitrary joins. Fix: its query model is primary key (+ indexes) lookups — a workload that needs ad-hoc joins across tables belongs on RDS/Aurora, however well the scale story fits DynamoDB.
- Not distinguishing gp3 from io2 by workload shape. Fix: gp3 is the balanced default; only reach for io2's guaranteed IOPS floor when a workload (a large relational database) is genuinely latency-sensitive and high-IOPS — defaulting to io2 everywhere pays for a guarantee most workloads don't need.
Check yourself — your primary RDS instance's AZ goes down. Does a Multi-AZ standby or a read replica fail over automatically, and why?
The Multi-AZ standby — it's a synchronous copy, so it can be promoted automatically with no data loss the moment the primary is unreachable. A read replica is asynchronous specifically so it doesn't add write latency to the primary, which means it can lag behind and has to be promoted manually.
Check yourself — you need object storage for build artifacts fetched by many independent CI jobs, no shared filesystem required. S3, EBS, or EFS?
S3 — it's reached for first for anything that's fundamentally a file to fetch: no server to manage, no capacity decision, and any number of clients can read it over HTTP. EFS would only earn its keep if the jobs needed to read/write the same files as a live filesystem at once.
You can defend this when you can pick between S3, EBS, and EFS from a workload's access pattern (not just its size), explain why an EBS snapshot stays cheap even on a large, frequently-changing volume, say why Aurora can fail over faster and support more read replicas than standard RDS, and explain — in terms of synchronous vs asynchronous replication — why a Multi-AZ standby can fail over automatically but a read replica can't.