Last updated:
Short answer: Use Amazon S3 for objects such as files, backups, images and data lakes that applications reach through an API. Use Amazon EBS as a low-latency disk attached to one EC2 instance, for boot volumes and databases. Use Amazon EFS when many Linux servers, containers or Lambda functions must share the same files over NFS.
S3 vs EBS vs EFS at a glance
| Amazon S3 | Amazon EBS | Amazon EFS | |
|---|---|---|---|
| Storage type | Object | Block (a virtual disk) | File (NFS v4.0 / v4.1) |
| How you access it | HTTPS API, SDK, CLI | Attached to an EC2 instance as a device, then formatted and mounted | Mounted as a shared folder by many clients |
| Scope | Regional bucket; most classes store data across 3 or more AZs | One Availability Zone | Regional (multi-AZ) or One Zone |
| Who can use it at once | Any number of clients | One instance (io1/io2 Multi-Attach: up to 16 Nitro instances in one AZ) | Many clients at once across AZs: EC2, ECS, EKS, Lambda, Fargate |
| Size | Unlimited objects; up to 48.8 TiB per object | gp3: 1 GiB to 64 TiB per volume | Grows and shrinks automatically to petabyte scale |
| Performance headline | Massive parallel throughput, millisecond first byte (Express One Zone: single-digit ms) | gp3: 3,000 IOPS and 125 MiB/s baseline, up to 80,000 IOPS and 2,000 MiB/s; io2 Block Express up to 256,000 IOPS | Elastic throughput scales with the workload; sub-millisecond latency on EFS Standard |
| Durability (designed for) | 99.999999999% (11 nines) | 99.8–99.9% (gp3, gp2, io1); 99.999% (io2) | 99.999999999% (11 nines) |
| Windows support | Yes, through the API | Yes | No (use FSx for Windows File Server) |
| You pay for | Data stored per class, requests, retrieval for some classes, data transfer | Provisioned size, plus extra IOPS/throughput where provisioned, plus snapshots | Data stored per class, throughput (Elastic or Provisioned), IA/Archive access |
| Typical uses | Static assets, uploads, backups, logs, data lakes, ML datasets | Boot volumes, self-managed databases, single-server apps | Shared web content, home directories, CI/CD build caches, containers needing shared state |
Figures from AWS documentation, checked October 9, 2026. Limits change, so confirm them in the linked docs before you design around them.
What is Amazon S3?
Amazon S3 (Simple Storage Service) stores data as objects inside buckets. An object is the file plus its metadata, addressed by a key such as reports/2026/q3.csv. You don’t mount S3 like a disk in its native form. Applications read and write objects through the S3 API, an AWS SDK or the CLI.
Facts worth remembering:
- Object size: a single
PUTuploads up to 5 GB. Multipart upload handles larger objects, up to 48.8 TiB (AWS also describes this as 50 TB) with up to 10,000 parts. The S3 console accepts uploads up to 160 GB. - Durability and availability: S3 is designed for 99.999999999% durability. S3 Standard is designed for 99.99% availability. Most storage classes store data across at least three Availability Zones. S3 One Zone-IA and S3 Express One Zone keep data in a single zone.
- Consistency: S3 gives strong read-after-write consistency for PUT and DELETE requests in all AWS Regions. After a successful write, the next read returns the new data.
- Storage classes: S3 Standard, Intelligent-Tiering, Express One Zone, Standard-IA, One Zone-IA, Glacier Instant Retrieval, Glacier Flexible Retrieval and Glacier Deep Archive. The infrequent-access classes carry minimum storage durations and a 128 KB minimum billable object size.
Use S3 when the data is written once and read many times, is shared with many clients, or needs to sit cheaply for years: user uploads, static website assets, log archives, database backups, data lakes and training data for ML. If you want to go deeper on buckets, lifecycle rules, encryption and bucket policies, the AWS S3 course covers them in labs.
What is Amazon EBS?
Amazon EBS (Elastic Block Store) provides block storage volumes for EC2. Think of an EBS volume as a network-attached hard disk. After you attach it, the instance sees a raw block device. You put a file system on it (XFS, ext4 or NTFS), mount it, and use it like any local disk.
Facts worth remembering:
- One Availability Zone: you can attach an EBS volume only to an instance in the same Availability Zone. To move data to another zone, take a snapshot and create a new volume from it there.
- Volume types:
gp3is the current General Purpose SSD and the default choice. It delivers a baseline of 3,000 IOPS and 125 MiB/s at any size, and you can provision up to 80,000 IOPS and 2,000 MiB/s on volumes from 1 GiB to 64 TiB.io2Block Express goes up to 256,000 IOPS and 4,000 MiB/s with 99.999% durability.st1andsc1are throughput-oriented HDD volumes for big sequential workloads and can’t be boot volumes. - Sharing: Multi-Attach works only with Provisioned IOPS
io1andio2volumes, on up to 16 Nitro-based instances in the same zone. Standard file systems such as XFS and ext4 aren’t built for this; you need a cluster-aware file system and an application that orders its writes. - Backups are your job: AWS does not back up EBS volumes automatically. EBS snapshots are incremental, are replicated across all Availability Zones in the Region, and can be restored in any zone in that Region. Schedule them with AWS Backup or Amazon Data Lifecycle Manager.
Use EBS when one server needs a fast, persistent disk: the root volume of every EC2 instance, a PostgreSQL or Oracle database you run yourself, or an application that expects a local disk.
Don’t confuse EBS with instance store. Some instance types include instance store volumes, which are physically attached temporary disks. Their data survives a reboot but not a stop, hibernation or termination. Use them only for caches and scratch data.
What is Amazon EFS?
Amazon EFS (Elastic File System) is a serverless, elastic file system that speaks NFS v4.0 and v4.1. Many clients mount the same file system at once and see the same directories, with strong consistency and file locking. You don’t provision capacity; it grows and shrinks as you add and remove files.
Facts worth remembering:
- File system types: Regional (recommended) stores data redundantly across multiple Availability Zones. One Zone keeps data in one zone at a lower cost and lower resilience.
- Clients: Amazon EC2, Amazon ECS, Amazon EKS, AWS Lambda and AWS Fargate can all mount EFS. Windows EC2 instances are not supported.
- Mount targets: clients connect through mount targets, one per Availability Zone. The mount target’s security group must allow inbound TCP 2049 (NFS) from your clients.
- Storage classes: EFS Standard, EFS Infrequent Access and EFS Archive, all designed for 11 nines of durability. Lifecycle management moves cold files to cheaper classes automatically. IA and Archive bill data access charges when files are read and have a 128 KiB minimum billing size per file.
- Throughput modes: Elastic (recommended default for most workloads, scales automatically), Provisioned (a fixed rate you pay for above the baseline) and Bursting (scales with the amount stored, using burst credits).
Use EFS when several Linux servers or containers need the same files: shared web content for a CMS, user home directories, build caches for CI/CD, or a shared model and asset folder for containers on ECS or EKS.
How do S3, EBS and EFS differ in practice?
Scope: Region or Availability Zone?
This is where most designs go wrong. S3 buckets are Regional and, in most storage classes, survive the loss of a whole Availability Zone. EFS Regional file systems are reachable from mount targets in every zone. EBS volumes are tied to one zone. If your Auto Scaling group launches an instance in us-east-1b, it cannot attach a volume that lives in us-east-1a.
Sharing: one writer or many?
S3 and EFS are built for many concurrent clients. EBS is built for one. Multi-Attach exists for clustered software that coordinates writes. It is not a shortcut to a shared drive.
Performance: latency or throughput?
EBS gives the lowest latency to a single instance because it behaves like a local disk. EFS adds network file system overhead but scales throughput across many clients. S3 has higher per-request latency than a disk, yet it can deliver very high aggregate throughput when many clients read large objects in parallel.
Durability and backup
S3 and EFS are designed for 11 nines and store data across zones (except the One Zone options). An EBS volume lives in one zone and is designed for 99.8–99.9% annual durability for most types (99.999% for io2). That is why snapshots matter: they protect you from both volume failure and your own mistakes.
How is each one priced?
This post doesn’t quote prices. They vary by Region and change over time. The pricing model is what affects architecture:
- S3: you pay per GB-month of data stored, by storage class, plus requests, retrieval fees on some classes and data transfer out. Check Amazon S3 pricing.
- EBS: you pay for the provisioned size per GB-month whether you use it or not. On
gp3, IOPS above 3,000 and throughput above 125 MiB/s cost extra. Snapshots are billed for the changed blocks they store. Check Amazon EBS pricing. - EFS: you pay for data stored per storage class. In Elastic mode you also pay for data and metadata transferred, and Provisioned mode bills throughput above the baseline. Check Amazon EFS pricing.
Practical tip: in Elastic throughput mode EFS meters each data I/O at a minimum of 32 KiB, so workloads with millions of tiny reads and writes can cost more than you expect. Test with real traffic before you commit.
Which one should you use? A decision guide
| Your situation | Pick | Why |
|---|---|---|
| Website images, user uploads, static assets | S3 | Any number of clients, 11 nines durability, no servers to manage |
| Root volume for an EC2 instance | EBS gp3 | Boot volumes need a block device |
| PostgreSQL, MySQL or Oracle that you run on EC2 | EBS gp3 or io2 | Low latency, consistent IOPS for one database server |
| WordPress or Drupal on several Linux web servers | EFS | Every server sees the same uploads and plugins folder |
| Shared folder for Windows servers | FSx for Windows File Server | EFS does not support Windows clients |
| Backups, logs, compliance archives | S3 with lifecycle rules to Glacier classes | Cheapest long-term storage, lifecycle automation |
| ML training data read by many jobs | S3 (add S3 Files if your tools need file paths) | Scales out, data stays in one place |
| Shared state for ECS or EKS containers | EFS | Pods and tasks move between nodes and zones; the files follow |
| Clustered app that writes one disk from two nodes | EBS io2 with Multi-Attach | Only with cluster-aware software; otherwise redesign |
To make the first questions concrete, here is a small Python rule-of-thumb picker. It is a teaching aid, not a sizing tool.
def pick_storage(access: str, shared: bool = False, client_os: str = "linux",
boot_or_db: bool = False) -> str:
"""Return a storage recommendation with a one-line reason.
access -- "object" (whole files over HTTP/API), "block" (a disk),
or "file" (a mounted folder with paths and locks)
shared -- True if several servers must read/write the same data
client_os -- "linux" or "windows"
boot_or_db -- True for a root volume or a self-managed database on EC2
"""
if access == "object":
return "Amazon S3: object storage over an API, any number of clients"
if boot_or_db or access == "block":
if shared:
return ("Amazon EBS io1/io2 with Multi-Attach (same AZ, Nitro, "
"cluster-aware file system) or rethink the design")
return "Amazon EBS (gp3 to start): a low-latency disk for one instance"
if access == "file":
if client_os == "windows":
return "Amazon FSx for Windows File Server: EFS does not support Windows"
return "Amazon EFS: shared NFS file system across instances and AZs"
raise ValueError("access must be 'object', 'block' or 'file'")
scenarios = [
("Static website images and user uploads", dict(access="object")),
("PostgreSQL you run yourself on EC2", dict(access="block", boot_or_db=True)),
("WordPress on 3 Linux web servers sharing wp-content",
dict(access="file", shared=True)),
("Shared drive for Windows app servers", dict(access="file", shared=True, client_os="windows")),
("Clustered app writing one disk from 2 nodes",
dict(access="block", shared=True)),
]
for name, kwargs in scenarios:
print(f"{name}\n -> {pick_storage(**kwargs)}")
Output (run with Python 3.13):
Static website images and user uploads
-> Amazon S3: object storage over an API, any number of clients
PostgreSQL you run yourself on EC2
-> Amazon EBS (gp3 to start): a low-latency disk for one instance
WordPress on 3 Linux web servers sharing wp-content
-> Amazon EFS: shared NFS file system across instances and AZs
Shared drive for Windows app servers
-> Amazon FSx for Windows File Server: EFS does not support Windows
Clustered app writing one disk from 2 nodes
-> Amazon EBS io1/io2 with Multi-Attach (same AZ, Nitro, cluster-aware file system) or rethink the design
What about Amazon S3 Files and Mountpoint for S3?
Two newer options blur the old “S3 is not a file system” rule, so it helps to know where they fit.
- Amazon S3 Files became generally available in April 2026. It is built using Amazon EFS and gives full file system access to data that stays in your S3 bucket. EC2 instances, Lambda functions, EKS and ECS clusters in the same VPC mount it through mount targets on NFS port 2049. The backing bucket needs versioning enabled. Choose it when your data already lives in S3 and file-based tools, such as ML data preparation or legacy batch jobs, need to read and write it without copying.
- Mountpoint for Amazon S3 is an open-source file client for high-throughput reads and new-file writes against S3. It does not support modifying existing files or deleting directories, so it isn’t a general shared file system.
Neither replaces EBS for a database, and neither is a reason to move a working EFS file system. They remove the need to copy S3 data into EFS just so a file-based tool can use it.
Hands-on: create one of each with the AWS CLI
This short lab makes the differences concrete. You will create an S3 bucket, a gp3 EBS volume and an EFS file system, use each from one EC2 instance, then delete everything.
Replace the placeholder IDs (i-1234567890abcdef0, sg-..., subnet-...) with your own.
Step 1: Create an S3 bucket and upload an object
Bucket names must be unique, so add your own suffix. In us-east-1 you don’t pass a location constraint.
aws s3api create-bucket --bucket pc-storage-demo-12345 --region us-east-1
echo "region,revenue" > report.csv
aws s3 cp report.csv s3://pc-storage-demo-12345/reports/report.csv
aws s3 ls s3://pc-storage-demo-12345/reports/
Expected output (illustrative):
{
"Location": "/pc-storage-demo-12345"
}
upload: ./report.csv to s3://pc-storage-demo-12345/reports/report.csv
2026-10-09 10:15:02 15 report.csv
Notice there is no mounting and no file system. You put and get whole objects by key.
Step 2: Create, attach and mount an EBS gp3 volume
Create the volume in the same Availability Zone as your instance.
aws ec2 create-volume \
--availability-zone us-east-1a \
--size 20 --volume-type gp3 --iops 3000 --throughput 125 \
--encrypted \
--tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=demo-ebs}]'
Expected output (illustrative, trimmed):
{
"AvailabilityZone": "us-east-1a",
"Encrypted": true,
"Size": 20,
"State": "creating",
"VolumeId": "vol-1234567890abcdef0",
"Iops": 3000,
"VolumeType": "gp3",
"MultiAttachEnabled": false,
"Throughput": 125
}
When the volume state is available, attach it:
aws ec2 describe-volumes --volume-ids vol-1234567890abcdef0 --query "Volumes[0].State"
aws ec2 attach-volume --volume-id vol-1234567890abcdef0 \
--instance-id i-1234567890abcdef0 --device /dev/sdf
"available"
{
"AttachTime": "2026-10-09T10:20:31.000Z",
"Device": "/dev/sdf",
"InstanceId": "i-1234567890abcdef0",
"State": "attaching",
"VolumeId": "vol-1234567890abcdef0"
}
Now SSH to the instance. On Nitro-based instances the volume appears as an NVMe device, so /dev/sdf shows up as something like nvme1n1. Always confirm with lsblk before formatting.
lsblk
sudo file -s /dev/nvme1n1 # "data" means no file system yet
sudo mkfs -t xfs /dev/nvme1n1 # only on a NEW, empty volume: this erases data
sudo mkdir /data
sudo mount /dev/nvme1n1 /data
df -h /data
Expected output (illustrative):
NAME MAJ:MIN RM SIZE RO TYPE MOUNTPOINT
nvme0n1 259:0 0 8G 0 disk
├─nvme0n1p1 259:1 0 8G 0 part /
└─nvme0n1p128 259:2 0 1M 0 part
nvme1n1 259:3 0 20G 0 disk
/dev/nvme1n1: data
Filesystem Size Used Avail Use% Mounted on
/dev/nvme1n1 20G 175M 20G 1% /data
This is block storage: a raw disk that you format and own. Only this one instance can mount it. The mount does not survive a reboot unless you add it to /etc/fstab (use the UUID and the nofail option).
Step 3: Create and mount an EFS file system
Create the file system with the recommended General Purpose performance mode and Elastic throughput:
aws efs create-file-system \
--performance-mode generalPurpose --throughput-mode elastic \
--encrypted --tags Key=Name,Value=demo-efs
{
"FileSystemId": "fs-0123456789abcdef0",
"LifeCycleState": "creating",
"NumberOfMountTargets": 0,
"PerformanceMode": "generalPurpose",
"Encrypted": true,
"ThroughputMode": "elastic"
}
Allow NFS from the instance’s security group to the mount target’s security group, then create a mount target in the instance’s subnet. In production, create one mount target in each Availability Zone you use.
aws efs describe-file-systems --file-system-id fs-0123456789abcdef0 \
--query "FileSystems[0].LifeCycleState"
aws ec2 authorize-security-group-ingress --group-id sg-0aaaaaaaaaaaaaaaa \
--protocol tcp --port 2049 --source-group sg-0bbbbbbbbbbbbbbbb
aws efs create-mount-target --file-system-id fs-0123456789abcdef0 \
--subnet-id subnet-0123456789abcdef0 --security-groups sg-0aaaaaaaaaaaaaaaa
Here sg-0aaaaaaaaaaaaaaaa is the mount target’s group and sg-0bbbbbbbbbbbbbbbb is the instance’s group.
"available"
{
"MountTargetId": "fsmt-0123456789abcdef0",
"FileSystemId": "fs-0123456789abcdef0",
"SubnetId": "subnet-0123456789abcdef0",
"LifeCycleState": "creating",
"IpAddress": "10.0.1.25",
"AvailabilityZoneName": "us-east-1a"
}
On the instance, install the EFS mount helper and mount with TLS so data is encrypted in transit:
sudo dnf install -y amazon-efs-utils
sudo mkdir -p /mnt/efs
sudo mount -t efs -o tls fs-0123456789abcdef0:/ /mnt/efs
df -h /mnt/efs
Filesystem Size Used Avail Use% Mounted on
127.0.0.1:/ 8.0E 0 8.0E 0% /mnt/efs
The huge size is not a mistake. EFS has no fixed capacity, so it reports a very large number and bills only for what you store. Mount the same file system on a second instance and both see the same files.
Step 4: Clean up
# On the instance
sudo umount /data /mnt/efs
# From your workstation
aws ec2 detach-volume --volume-id vol-1234567890abcdef0
aws ec2 delete-volume --volume-id vol-1234567890abcdef0 # after it shows "available"
aws efs delete-mount-target --mount-target-id fsmt-0123456789abcdef0
aws efs delete-file-system --file-system-id fs-0123456789abcdef0 # after mount targets are gone
aws s3 rb s3://pc-storage-demo-12345 --force # deletes all objects, then the bucket
If you repeat labs like this often, wrap the create and cleanup commands in a script with set -euo pipefail and checks between steps. The Bash Scripting: Zero to Pro tutorial shows the patterns.
Common mistakes with S3, EBS and EFS
- Expecting an EBS volume to follow an instance to another zone. It can’t. Snapshot it and create a new volume in the target zone, or use EFS or S3 for data that must be reachable from every zone.
- Using Multi-Attach as a shared drive. Mounting one XFS or ext4 volume read-write on two instances corrupts data. Multi-Attach needs a cluster-aware file system.
- Planning EFS for Windows servers. It isn’t supported. Use FSx for Windows File Server.
- Treating S3 as a POSIX file system. Mountpoint for S3 can’t modify existing files. If tools need real file semantics on S3 data, evaluate S3 Files.
- Paying for forgotten EBS volumes. EBS bills for provisioned size even when unattached. Volumes kept after termination (
DeleteOnTerminationset to false) keep incurring charges until you delete them. - Assuming AWS backs up EBS for you. It doesn’t. Automate snapshots with AWS Backup or Data Lifecycle Manager and test a restore.
- Putting valuable data on instance store. It is erased on stop, hibernation and termination.
A real-world example: one web application, all three services
A common three-tier design on AWS uses each service for what it does best:
- EC2 web servers in an Auto Scaling group across two zones, each with an EBS gp3 root volume. These are disposable: if one fails, the group replaces it.
- User uploads and static assets in S3, served through a CDN. The web servers don’t store them locally, so any server can handle any request.
- A shared EFS file system only for the parts of a legacy CMS that insist on a shared folder, such as a plugins or cache directory, with a mount target in each zone.
- The database on Amazon RDS (managed) or, if you must run it yourself, on EC2 with an io2 or gp3 volume and scheduled snapshots.
- Backups, logs and snapshot exports in S3, with lifecycle rules that move old data to Glacier storage classes.
Choosing storage is a recurring theme in AWS Solutions Architect Associate exam scenarios. If you’re preparing for the exam, practice spotting the clue words: “shared”, “POSIX”, “single AZ”, “archive”, “boot volume”. The AWS Solutions Architect course drills these scenarios in labs.
Frequently asked questions
Is S3 faster than EBS?
For a single server reading and writing small blocks, no. EBS is a disk attached to the instance and is built for low-latency I/O. S3 is accessed over an API and shines at large objects and massive parallel throughput from many clients. Pick by access pattern, not by a single speed number.
Can I attach one EBS volume to multiple EC2 instances?
Only Provisioned IOPS io1 and io2 volumes with Multi-Attach, up to 16 Nitro-based instances in the same Availability Zone, and your software must coordinate writes with a cluster-aware file system. For ordinary shared files across servers, use Amazon EFS.
Can Amazon EFS be used with Windows?
No. AWS states that using Amazon EFS with Microsoft Windows-based EC2 instances is not supported. For shared SMB file storage for Windows, use Amazon FSx for Windows File Server.
Which is cheapest: S3, EBS or EFS?
It depends on the workload. S3 bills for data stored per storage class plus requests and transfer. EBS bills for the size you provision, even if the disk is empty. EFS bills for data stored per storage class plus throughput in Elastic mode. Model your own numbers in the AWS Pricing Calculator.
Is Amazon S3 Files the same as Amazon EFS?
No. S3 Files, generally available since April 2026, is built using Amazon EFS but gives file system access to data that stays in an S3 bucket. EFS is a standalone file system that holds its own data. Use S3 Files when the data already lives in S3 and file-based tools need to read and write it.
What happens to an EBS volume when I terminate the instance?
It depends on the DeleteOnTermination setting. If it is true, the volume is deleted with the instance. If it is false, the volume is kept and keeps incurring charges until you delete it. Instance store data, by contrast, does not survive a stop or termination.
Sources
All checked on October 9, 2026.
- Amazon S3: What is Amazon S3? (strong consistency), multipart upload limits, uploading objects, storage classes, data protection and durability, S3 FAQs (Mountpoint)
- Amazon S3 Files: launch announcement, April 2026, mounting S3 buckets on compute
- Amazon EBS: volume types, General Purpose SSD (gp3), Multi-Attach, snapshots, restore a volume (same-AZ requirement), make a volume available on Linux
- Amazon EC2: instance store
- Amazon EFS: What is Amazon EFS?, storage classes, performance and throughput modes, network access and security groups, EFS on Amazon Linux 2023
- Amazon FSx: What is FSx for Windows File Server?
- Pricing: Amazon S3, Amazon EBS, Amazon EFS
Train your team on this. If your team needs hands-on AWS training on storage, networking and architecture, see AWS training for teams and live batches. For an existing design you’d like reviewed, see AWS consulting.
More AWS guides and labs: AWS tutorials and guides.
Newsletter
Enjoyed this post?
Get new posts, AI/ML tutorials, AWS batch dates and Oracle tips by email. No spam, unsubscribe anytime.