What's the Difference Between EBS IOPS and Physical Disk IOPS
Published 2026-08-13 · Updated 2026-08-13 · Last Verified 2026-08-13
Answer
EBS IOPS is not a physical-device performance figure — it is a ceiling set by the service. EBS is block storage attached over the network, with IOPS and throughput (MiB/s) ceilings determined by the volume type and provisioned amount. On top of that, a separate EBS bandwidth ceiling exists on the instance side, so attaching a large volume to a small instance will hit the instance-side ceiling first. This means you cannot directly compare a physical disk benchmark figure with an EBS number.
Applicability of This Document
| Product | Amazon EBS (gp2 / gp3 / io1 / io2 / st1 / sc1), Amazon EC2 instance store |
|---|---|
| Verified Versions | AWS CLI v2 / the public APIs of Amazon EC2 and Amazon CloudWatch, fio 3.x (based on the specification as of 2026-08-13) |
| Environment | AWS (EC2, EBS); on-premises physical disks for comparison |
| Required Permissions | Read access requires `ec2:DescribeVolumes` and `cloudwatch:GetMetricStatistics`. Running fio requires access to the target device/file on the OS |
| Execution Impact | No impact from read commands. fio generates I/O load, affecting the performance of co-located processing |
| Restart | Not required |
| Last Verified | 2026-08-13 |
Ready-to-Run Commands
- 対象
- Amazon EBS (AWS CLI v2)
- 権限
- ec2:DescribeVolumes
- 変更作業
- None (read-only)
- Production実行
- Possible
# 対象: Amazon EBS(AWS CLI v2)
# 権限: ec2:DescribeVolumes
# 変更作業: なし(参照のみ)
# Production 実行: 可能
aws ec2 describe-volumes \
--volume-ids vol-0123456789abcdef0 \
--query "Volumes[].{Id:VolumeId,Type:VolumeType,SizeGiB:Size,Iops:Iops,\
ThroughputMiBs:Throughput,MultiAttach:MultiAttachEnabled,State:State,\
AttachedTo:Attachments[0].InstanceId,Device:Attachments[0].Device}" \
--output table`Iops` and `Throughput` are provisioned values. `Throughput` is the throughput value configurable on gp3 and may not be returned for other types. What you see here is the ceiling on the volume side — the EBS bandwidth ceiling on the attached instance's side needs to be checked separately.
- 対象
- Amazon CloudWatch (namespace AWS/EBS)
- 権限
- cloudwatch:GetMetricStatistics
- 変更作業
- None (read-only)
- Production実行
- Possible
# 対象: Amazon CloudWatch(名前空間 AWS/EBS)
# 権限: cloudwatch:GetMetricStatistics
# 変更作業: なし(参照のみ)
# Production 実行: 可能
for M in VolumeReadOps VolumeWriteOps VolumeQueueLength BurstBalance
do
echo "===== $M ====="
aws cloudwatch get-metric-statistics \
--namespace AWS/EBS \
--metric-name "$M" \
--dimensions Name=VolumeId,Value=vol-0123456789abcdef0 \
--start-time 2026-08-12T00:00:00Z \
--end-time 2026-08-13T00:00:00Z \
--period 300 \
--statistics Average Maximum Sum \
--output text
done`VolumeReadOps` and `VolumeWriteOps` are the **total number of I/O operations** within the period. To convert to IOPS (per second), divide the Sum by the number of seconds in the period (divide by 300 for `--period 300`). `BurstBalance` is meaningful only for types that use burst credits (gp2, st1, sc1); if the value keeps dropping, credits are being consumed.
- 対象
- Amazon Linux / Ubuntu, etc. (the OS on EC2)
- 権限
- Can be run as a regular user (the nvme command may require root)
- 変更作業
- None (read-only)
- Production実行
- Possible
# 対象: EC2 上の Linux
# 権限: 一般ユーザー(nvme list は root 権限が必要な場合がある)
# 変更作業: なし(参照のみ)
# Production 実行: 可能
lsblk -o NAME,SIZE,TYPE,MOUNTPOINT,MODEL
sudo nvme list
cat /sys/block/nvme1n1/queue/nr_requests
iostat -x 1 5On Nitro-generation instances, EBS volumes also appear as NVMe devices. A device name being NVMe does not mean it's "physically direct-attached." The model name from `nvme list` lets you distinguish an EBS volume from instance store.
- 対象
- Linux + fio 3.x
- 権限
- Read access to the target file/device (root if targeting a device directly)
- 変更作業
- None (read-only), but it generates I/O load
- Production実行
- Not recommended. Don't run this against storage shared with production
# 対象: Linux + fio 3.x
# 権限: 対象ファイルへの読み取り権限(デバイス直接指定なら root)
# 変更作業: なし(読み取りのみ)だが、実行中は他の処理の I/O 性能に影響する
# Production 実行: 非推奨。検証環境、または本番と共有しないボリュームで実行すること
fio --name=randread \
--filename=/mnt/testdir/fio_testfile \
--size=64G \
--rw=randread \
--bs=4k \
--ioengine=libaio \
--direct=1 \
--iodepth=32 \
--numjobs=4 \
--runtime=300 \
--time_based \
--group_reporting`--direct=1` bypasses the OS page cache; without it, you'd be measuring cache hits and getting memory performance instead of storage performance. Set `--size` well above the amount of RAM (if the working set fits in memory, you're again measuring the cache). A measurement missing either of these two is meaningless, whether on a physical disk or on EBS.
How to Read the Results
| Column | Meaning | What to Check |
|---|---|---|
| VolumeType | Volume type (gp2 / gp3 / io1 / io2 / st1 / sc1) | How the ceiling is determined differs by type: gp2 is capacity-linked plus burst, gp3 is a baseline plus additional settings, io1/io2 is provisioned |
| Size | Volume size (GiB) | On gp2, capacity is directly tied to baseline performance. On gp3, capacity and performance settings are independent |
| Iops | Provisioned IOPS ceiling | This is "the value it won't exceed," not "the value it can deliver." If measured usage is pegged here, this is the limiting factor |
| Throughput | Provisioned throughput (MiB/s) | Even with IOPS headroom, this can become the ceiling — workloads with a large I/O size hit it first |
| Attachments[0].InstanceId | The attached instance | Check that instance class's EBS bandwidth ceiling in current AWS documentation. If lower than the volume's ceiling, the instance is the limiting factor |
| VolumeReadOps / VolumeWriteOps | Total I/O operations within the period | Divide the Sum by the number of seconds in the period to convert to IOPS, and compare against the provisioned value |
| VolumeQueueLength | Average number of outstanding I/O requests | Consistently high means storage cannot keep up with requests. If it stays low while things are slow, the limiting factor is something other than storage |
| BurstBalance | Remaining burst credit (%) | Applies only to gp2, st1, sc1. If it keeps dropping, performance will fall to baseline once credits run out |
When to Use This
- Performance that was achieved on on-premises SSD is not reproduced after moving to EBS
- A benchmark tool's numbers diverge significantly from EBS's provisioned values
- Increasing a volume's IOPS doesn't raise throughput
- A large volume was attached, but the expected performance is not achieved
- A gp2 volume is fast for a while, then suddenly slows down at some point
- CloudWatch's VolumeReadOps value doesn't line up with IOPS units
Possible Causes (Most Likely First)
01
EBS is network-attached block storage
EBS is not a device physically attached to the instance — it is storage connected over the network. IOPS is therefore determined not by "how fast the device is" but by "how much the service lets through." Because it goes over the network, latency characteristics also differ from a physical disk.
02
I/O size changes how many IOPS a single operation consumes
EBS counts I/O in fixed-size units. An I/O larger than that unit is counted as multiple IOPS, while consecutive I/O can sometimes be counted together. In other words, "one operation" does not equal "one IOPS." The unit size differs by volume type (SSD-based vs. HDD-based), so check the current EBS volume type documentation for the value for your type — this article does not give specific byte figures.
03
IOPS and throughput are separate ceilings
EBS has two ceilings: IOPS (operations/sec) and throughput (MiB/sec). A workload issuing many small I/Os hits the IOPS ceiling first, while one issuing large I/Os hits the throughput ceiling first. Judge which is the limiting factor by whether I/O size times IOPS has reached the throughput ceiling.
04
The instance side also has an EBS bandwidth ceiling
In addition to the volume-side ceiling, each EC2 instance class has a defined bandwidth ceiling to EBS (EBS-optimized bandwidth). Attaching a high-performance volume to a small instance means the instance-side ceiling becomes the bottleneck. Since the ceiling differs by instance class, check the target class in current AWS documentation.
05
gp2 depends on burst credits
gp2 has a baseline performance tied to capacity, with I/O beyond that drawn from I/O credits. Once credits run out, performance falls to baseline. This is the classic cause of "fast at first, then slows down at some point." gp3 is not credit-based — it is a model where additional IOPS and throughput are configured on top of a baseline.
06
Confusion with instance store (NVMe)
Instance store is an NVMe device physically attached to the host, and it is not subject to a network-based ceiling like EBS. However, it is temporary storage that loses data on instance stop or termination. Benchmarking instance store and comparing the result against EBS numbers will always produce a mismatch.
07
The benchmark is measuring the cache
If `direct=1` is not specified, or the test data size is smaller than RAM, what's being measured is the OS page cache. A figure obtained under these conditions does not represent storage performance, on a physical disk or on EBS.
Diagnostic Steps
- 1
Check the volume-side ceiling
Read-onlyUse `aws ec2 describe-volumes` to check the type, capacity, provisioned IOPS, and throughput setting.
- 2
Check the instance-side ceiling
Read-onlyCheck the attached instance class's EBS bandwidth ceiling in current AWS documentation. If lower than the volume side, the instance is the limiting factor.
- 3
Pull measured values from CloudWatch
Read-onlyGet the Sum of VolumeReadOps/VolumeWriteOps and divide by the number of seconds in the period to convert to IOPS. Also check VolumeQueueLength and BurstBalance.
- 4
Check the I/O size
Read-onlyDivide throughput (bytes/sec) by IOPS (ops/sec) to get the average I/O size. This is a basis for judging whether the limit is IOPS or throughput.
- 5
Check the OS-side view
Read-onlyUse `iostat -x` to check `r/s`, `w/s`, `aqu-sz`, `await`, and `%util`, and cross-check against the CloudWatch values.
- 6
Run fio in a test environment if needed
LowAlways specify `--direct=1` and a working set larger than RAM. Do not run this against a volume shared with production.
Solutions
Low-risk action that can be done immediately
Identify a single ceiling that is being hit
Read-onlyIdentify whether it's the volume's IOPS ceiling, the volume's throughput ceiling, the instance's EBS bandwidth ceiling, or burst credit exhaustion. Without pinning this down, any configuration change is guesswork.
Align benchmark conditions before comparing
Read-onlyCheck whether `direct=1` was specified, whether the working set is larger than RAM, and whether I/O size and queue depth match between the figures being compared. Numbers under different conditions cannot be compared.
Change requiring advance review
Review volume type and provisioned values
MediumReview IOPS if IOPS-bound, or the throughput setting if throughput-bound. If credit exhaustion is occurring on gp2, consider switching to gp3.
Review the instance class
MediumIf the instance-side EBS bandwidth is the limiting factor, no amount of volume improvement will help. Consider a class with higher EBS bandwidth.
Review the application's I/O size and queue depth
MediumIf many small I/Os are being issued, batching them can reduce IOPS consumption. For a database, this corresponds to page size or read-ahead settings.
Change involving a restart or service impact
Switch to a configuration using instance store
HighInstance store loses data on stop or termination. It cannot be used for data that needs to persist. Limit its use to cache or temporary space, and pair it with an operational design that assumes data loss.
Change the volume type
HighA type change (e.g., gp2 → gp3) can cause temporary performance fluctuation during the change. Check current AWS documentation for eligibility and duration, and carry it out during a window with minimal business impact.
!Warnings
- This article gives no specific EBS IOPS, throughput, or latency figures. Ceiling values are determined by type, capacity, and instance class, and are also revised over time. Always check current AWS documentation for the values for your target configuration.
- fio generates actual I/O load. Running it against the same volume as production, or an instance sharing EBS bandwidth with production, affects the performance of business processing. Run it in a test environment.
- A measurement without `--direct=1`, or with a working set smaller than RAM, is measuring the page cache, not storage. You cannot compare that number against EBS or a physical disk.
- Burst credit exhaustion on gp2 cannot be detected with a short benchmark. Check the BurstBalance trend over a long period.
- On Nitro-generation instances, EBS volumes also appear as NVMe devices. Don't conclude "physically direct-attached" just from the device name.
- Instance store loses data on instance stop or termination. Don't choose it as a place for persistent data based on performance figures alone.
Differences by Version and Environment
If This Doesn't Resolve It
Check the filesystem and mount options
Alignment, journaling settings, and whether `noatime` is set affect I/O count. Check this when things are slow without hitting a block-device ceiling.
Check the application's synchronous I/O settings
A database log write is synchronous I/O, where latency matters more than throughput. Check this if things are slow despite headroom in IOPS.
Check for waiting at the RAID or LVM layer
When striping multiple volumes, a single slow one drags down the whole array. Check `iostat -x` per device.
Check for contention with the instance's network bandwidth
How EBS bandwidth and network bandwidth are handled differs by generation and class. Worth checking if I/O drops during heavy network traffic.
Obtain the measurement conditions for anything being compared
If the measurement conditions (I/O size, queue depth, direct flag, working set) behind a claim like "on physical disk it was this value" are unknown, the comparison itself does not hold.
Basis and Limitations of This Document
Explanation based on official product documentation
Based on the public specifications of Amazon EBS volume types, the provisioning model, and EBS-optimized instance bandwidth, the AWS/EBS namespace metrics in Amazon CloudWatch (VolumeReadOps, VolumeWriteOps, VolumeQueueLength, BurstBalance), and the public option specifications of fio. Specific ceiling and measured values are not included in the body text because they are revised over time — check current AWS documentation for values matching your target configuration.
FAQ
Does EBS IOPS mean the same thing as physical disk IOPS?
No. Physical disk IOPS is a performance characteristic of the device, while EBS IOPS is a ceiling applied by the service. EBS is network-attached block storage and cannot exceed the provisioned value. The two numbers cannot be compared directly.
Does raising a volume's IOPS always make it faster?
No. If the throughput (MiB/s) ceiling is being hit, raising IOPS will not help. And if the instance class's EBS bandwidth ceiling is lower, strengthening the volume will only hit the instance-side ceiling instead. Identify which ceiling is being hit first.
Why does an HDD RAID 0 configuration show an extremely high IOPS number?
You are almost certainly measuring something other than the device's performance — typically the OS page cache, a RAID controller's write-back cache, or a sequential access pattern. True random I/O on rotating media is dominated by seek and rotational latency, so a cache-bypassed measurement (`direct=1` plus a working set larger than RAM, `rw=randread`) will not produce the same number. Check the measurement conditions.
Is CloudWatch's VolumeReadOps the same as IOPS?
Not as-is. VolumeReadOps/VolumeWriteOps is the total number of I/O operations within the period. To convert to IOPS (per second), divide the Sum statistic by the number of seconds in the period — divide by 300 for `--period 300`.
Can instance store be used to avoid EBS's ceiling?
In terms of the storage ceiling, yes, but instance store is temporary storage that loses data on stop or termination. It cannot be used for data that needs to persist. Limit its use to cache or temporary space, and consider it alongside an operational design that assumes data loss.
Can this be run in production?
`describe-volumes`, the CloudWatch retrieval, and `lsblk`/`iostat` are read-only and can be run in production as well. Since fio generates actual I/O load, do not run it against an environment sharing a volume or EBS bandwidth with production.
Questions This Document Covers
- Why does HDD RAID 0 show a high IOPS value
- Why doesn't raising EBS IOPS make things faster
- Can't get the same performance on EBS as on-premises SSD
- How to convert CloudWatch's VolumeReadOps to IOPS
What the Risk Labels Mean
- Read-onlyDoes not change data or settings.
- LowImpact is limited, but permissions and load should be checked.
- MediumMay affect performance, locking, or cost.
- HighMay cause an outage, data loss, or require recovery work.
- Expert Review RequiredRequires a separate review before applying to production.
GIIP's Scope of Support
Where an EBS ceiling applies can be figured out in a single investigation once conditions are matched. What matters operationally isn't that — it's whether you notice the moment data volume and access patterns shift enough to start hitting the ceiling. At GIIP, an AI agent continuously tracks storage-side leading indicators such as VolumeQueueLength and BurstBalance across several databases on AWS and Azure and roughly 30 web services, and a human specialist judges whether a configuration change is needed once a trend approaches the ceiling. The goal is to detect this before it becomes an incident, not to measure it afterward.
Author & Technical Review
GIIP Production Operations Team
About 30 years of experience in designing, migrating, and operating large-scale web services, SQL Server, Oracle, AWS, and Azure. Experience includes 12 sets of x12large-class AWS RDS for SQL Server environments, an Oracle environment with roughly 120,000 tables, and migrating roughly 3TB from TiDB to Aurora MySQL. AI agents and human experts currently continue to monitor and operate multiple cloud databases and about 30 web services.
Random IOPS vs. Sequential IOPS, and How to Read Benchmark Results
A document organizing why an IOPS figure cannot be compared without I/O size, queue depth, and read/write ratio, and how to build measurement conditions with fio.
awsThe Difference Between One Large RDS Instance and Several Smaller Instances
A document organizing the technical differences between "one large instance" and "several smaller instances" for RDS sizing, and the CloudWatch metrics you should measure before deciding.
awsWhat to Check When Reviewing AWS Database Costs
A checklist for reviewing AWS database spend in order of increasing impact: stop what is unused → right-size → storage → backups → non-production → commitments.
monitoringWhat to Configure When Monitoring Servers and Databases 24/7
A checklist, organized by layer, of what to monitor, how to think about thresholds, the escalation structure, and why synthetic monitoring is necessary when designing 24/7 monitoring.
Related Services
Request an investigation into an EBS performance bottleneck
If you need to repeat the same checks across multiple environments, we can discuss your entire operations setup.
Request an investigation into an EBS performance bottleneck