S3 vs EBS vs EFS: Object, Block or File Storage on AWS
8 min readBytePatterns
S3 vs EBS vs EFS: objects by key over HTTP, a block disk tied to one instance in one zone, or a file system many instances mount across zones, and which fits.
S3 vs EBS vs EFS in one line: S3 stores objects that you address by key over HTTP, EBS is a block device attached to one EC2 instance in one Availability Zone, and EFS is a network file system that many instances mount at once across zones. They are not three tiers of the same thing. They answer three different questions: how is the data addressed, how many machines touch it, and from where. Facts come from the AWS documentation listed at the end, as of October 2026.
| Service | What you get | Who can reach it |
|---|---|---|
| S3 | objects by key, over an HTTPS API | anything with credentials and a network path, Region-wide |
| EBS | a block volume with a file system you format | one instance, in the volume's Availability Zone |
| EFS | a POSIX file tree over NFS | many instances, containers and functions, across zones |
The problem it solves
A photo service has four kinds of data: the uploaded images, the database's data directory, the web servers' root disks, and a shared folder of generated thumbnails that three servers write into. Putting all four in one place is wrong in both directions. The images on a block volume cannot be served from other zones; the database on an object store has no file system to write pages to; the shared folder on a disk belongs to exactly one server.
The S3 lesson covers how one of these three ages data out over time. This article is the choice before that: which store the data belongs in at all.
The intuition
Start from how the application talks to the data.
- S3 is a key-value store for blobs. A bucket lives in a Region, and every object is a key plus bytes, written and read whole through an HTTP API:
PutObject,GetObject,ListObjectsV2. There is no file system, no partial in-place write and no mounting in the ordinary sense; Mountpoint for Amazon S3 gives a file-like client, but it is not a general-purpose POSIX disk. In return S3 is designed for eleven nines of durability, scales without you provisioning anything, serves clients anywhere, and has storage classes with lifecycle rules that move cold objects to cheaper classes and expire them. Reads after a successful write are strongly consistent. - EBS is a disk. A volume is created in one Availability Zone and attached to one instance there, where the operating system formats it and uses it like a local drive. Volume types trade cost for performance:
gp3for general-purpose SSD,io2for provisioned IOPS,st1andsc1for throughput-oriented and cold HDD. The exception to "one instance" is Multi-Attach forio1andio2, which allows several instances in the same zone to attach one volume, and only with a cluster-aware file system. A snapshot is an incremental copy stored by the EBS service in S3, and it is how a volume moves to another zone or Region: snapshot, then create a new volume from it. - EFS is a shared file system. It speaks NFS, and instances in every Availability Zone of the Region mount it through mount targets; Lambda functions and ECS and EKS containers can mount it too. It grows and shrinks as files are added and removed, so there is no size to provision. A Standard file system stores data across multiple zones; One Zone stores it in one zone for less. Like S3 it has storage classes, Standard, Infrequent Access and Archive, with lifecycle management that moves files that have not been read for a while. Per gigabyte stored, Standard EFS is the most expensive of the three.
Then read the decision off the workload:
- The application reads and writes whole blobs, serves them to users, or keeps backups and logs: S3.
- One machine needs a disk: a root volume, a database's data directory, anything that expects a block device: EBS.
- Several machines need the same directory tree with file semantics: EFS.
Watch it run
The lesson animation shows the part of S3 that neither of the other two offers in the same shape. An overwrite is readable immediately, because reads after a write are strongly consistent. Then one object walks down the storage classes under a lifecycle rule, from Standard to Standard-IA to Glacier Flexible Retrieval, where a read first needs a restore, until the expiration action deletes it. An EBS volume has snapshots instead of classes, and EFS has its own Infrequent Access and Archive classes for files, but only S3 lets you age an object through a retrieval model like that.
S3: Consistency, Classes, Lifecycle
Step 1 of 10
A bucket is a flat namespace of keys. Every object also has a storage class; Standard is the default.
The same interactive animation as the lesson — step through it with the controls.
The code
The lesson's lifecycle configuration, which exists only for S3, is illustrative and needs an account:
{"Rules": [{"ID": "age-out", "Status": "Enabled", "Filter": {"Prefix": "raw/"},
"Transitions": [{"Days": 30, "StorageClass": "STANDARD_IA"},
{"Days": 180, "StorageClass": "GLACIER"}],
"Expiration": {"Days": 365}}]}
A toy model of the decision, not of any AWS API. Each workload is described by how it addresses data, how many writers share it and how far away they are, and the classifier reads the table above:
WORKLOADS = {
"user uploads served over HTTPS": {"access": "object", "sharers": "many", "scope": "region"},
"nightly database backups": {"access": "object", "sharers": "one", "scope": "region"},
"root volume of a web server": {"access": "block", "sharers": "one", "scope": "az"},
"PostgreSQL data directory": {"access": "block", "sharers": "one", "scope": "az"},
"shared /home for a training cluster": {"access": "file", "sharers": "many", "scope": "region"},
"WordPress uploads behind 3 servers": {"access": "file", "sharers": "many", "scope": "region"},
}
def decide(need):
"""Toy model of the decision: how the data is addressed, by how many, from where."""
if need["access"] == "object":
return "S3" # keys over HTTP, from anywhere in the Region or beyond
if need["access"] == "block":
return "EBS" # a disk; one instance, one Availability Zone
if need["access"] == "file" and need["sharers"] == "many":
return "EFS" # a POSIX tree mounted by many, across zones
return "EBS with a file system on it"
for name, need in WORKLOADS.items():
print(f"{name:38} -> {decide(need)}")
# user uploads served over HTTPS -> S3
# nightly database backups -> S3
# root volume of a web server -> EBS
# PostgreSQL data directory -> EBS
# shared /home for a training cluster -> EFS
# WordPress uploads behind 3 servers -> EFS
Next, the reach of each store. Three instances, one in zone 1a and two in 1b; a bucket, a volume attached to web-2, a Standard EFS file system and a One Zone file system in 1a:
INSTANCES = {"web-1": "us-east-1a", "web-2": "us-east-1b", "web-3": "us-east-1b"}
STORES = {
"S3 bucket photos": {"kind": "S3", "az": None, "attach": None},
"EBS volume vol-0a1b": {"kind": "EBS", "az": "us-east-1b", "attach": "web-2"},
"EFS fs-77 (Standard)": {"kind": "EFS", "az": None, "attach": None},
"EFS fs-99 (One Zone, 1a)": {"kind": "EFS", "az": "us-east-1a", "attach": None},
}
def reachable(store, instance):
"""Toy model: can this instance read and write this store?"""
az = INSTANCES[instance]
if store["kind"] == "S3":
return True # an HTTP endpoint in the Region
if store["kind"] == "EBS":
return store["attach"] == instance # attached to exactly one instance
if store["az"] is None:
return True # Standard EFS: mount targets in every zone
return store["az"] == az # One Zone EFS: mount from that zone
print(f"{'':26}" + "".join(f"{i:>8}" for i in INSTANCES))
for name, store in STORES.items():
print(f"{name:26}" + "".join(f"{str(reachable(store, i)):>8}" for i in INSTANCES))
# web-1 web-2 web-3
# S3 bucket photos True True True
# EBS volume vol-0a1b False True False
# EFS fs-77 (Standard) True True True
# EFS fs-99 (One Zone, 1a) True False False
The volume reaches one instance; web-3, in the same zone, could attach it only after web-2 detaches it, or with Multi-Attach on an io2 volume. The One Zone file system is mounted from its own zone; in practice you can reach it from other zones over the network at a cost, which this toy leaves out.
The complexity
The costs are not comparable per gigabyte alone, because the units differ:
- S3 bills storage per gigabyte per class, plus requests and data transfer out. Objects can be any size up to five terabytes and the bucket has no size to plan.
- EBS bills provisioned size, and for
gp3andio2also provisioned IOPS and throughput, whether used or not. A volume's performance and failure domain are one zone. - EFS bills what is stored, per class, with throughput as a separate dimension. Latency per operation is network latency, higher than a local block volume, and the shared tree is what you pay for.
Where it goes wrong
- A database on S3. Engines write pages in place to a block device; S3 has objects, not pages. Use EBS, or a managed database.
- An EBS volume as shared storage. A volume attaches to one instance; two web servers cannot both write the same volume unless it is Multi-Attach
io2in one zone with a cluster file system. Use EFS, or put the files in S3. - Static files on EFS when they are served to the public. EFS is for processes that need a file system. Files served over HTTP belong in S3, usually behind CloudFront.
- Treating a snapshot as a backup in another zone without creating a volume from it. The snapshot is the copy; the volume you restore from it is what an instance can use.
- Forgetting that EFS is priced per gigabyte stored. Thousands of small, rarely read files are cheaper in S3 or in EFS Infrequent Access.
When it shows up in interviews
As a design follow-up once the instances are drawn: "where does the data live?" The strong answer names a store per kind of data, not one for everything, and says why the uploads cannot be on a disk and the database cannot be in a bucket. In certification questions the distractor is usually a shared directory, where EBS is the wrong answer because it attaches to one instance.
How to say it in an interview
"S3 is object storage: whole blobs by key over HTTP, durable, Region-wide, with storage classes and lifecycle rules, so uploads, backups and static assets go there. EBS is a block volume for one EC2 instance in one zone, so boot disks and database data directories go there, with snapshots for copies. EFS is a shared NFS file system that many instances or containers mount across zones, for anything that needs a common directory tree. I pick by how the data is addressed and how many machines share it, not by size."
Related reading: how zones and subnets are laid out in AWS VPC subnets, security groups and NACLs, and the same "which service" shape for compute in Lambda vs Fargate vs EC2.
Frequently asked questions
What is the difference between S3, EBS and EFS?
S3 is object storage: objects by key over an HTTP API, Region-wide, with storage classes and lifecycle rules. EBS is block storage: a volume attached to one EC2 instance in one Availability Zone. EFS is file storage: an NFS file system that many instances, containers and functions mount at the same time across zones.
Can EBS be attached to multiple instances?
Normally no: a volume attaches to one instance in its Availability Zone. The exception is Multi-Attach for io1 and io2 volumes, which lets several instances in the same zone attach one volume, and it needs a cluster-aware file system. For an ordinary shared directory, use EFS instead.
When should I use EFS instead of S3?
When processes need a real file system: paths, directories, file locks, partial writes and POSIX permissions, shared by several instances or containers. If the application only stores and fetches whole files, or serves them to users over HTTP, S3 is cheaper and simpler, and it needs no mount.
Sources
- What is Amazon S3? — Amazon S3 User Guide
- Understanding and managing Amazon S3 storage classes — Amazon S3 User Guide
- Managing the lifecycle of objects — Amazon S3 User Guide
- What is Amazon Elastic Block Store? — Amazon EBS User Guide
- Amazon EBS volume types — Amazon EBS User Guide
- Attach an Amazon EBS volume to multiple instances using Multi-Attach — Amazon EBS User Guide
- What is Amazon Elastic File System? — Amazon EFS User Guide
- EFS storage classes — Amazon EFS User Guide
- Managing file system storage with lifecycle management — Amazon EFS User Guide