Course outline

5.2

EBS Volume Types, Multi-Attach and Encryption

gp3 vs gp2 vs io2 Block Express vs st1 vs sc1, Multi-Attach, and encrypting an existing volume.

26 min Reading + animations

Tip: tap or hover any dotted-underlined term to see what it means.

By the end of this lesson you will be able to

  • Explain IOPS, throughput and latency, and calculate one from the others with the I/O size.
  • Describe the six current EBS volume types (gp3, gp2, io2 Block Express, io1, st1, sc1) with their real limits, and say which can be boot volumes.
  • Explain the gp2 burst bucket, calculate how long a small gp2 volume can burst, and say why gp3 removes the problem.
  • Recognise when the instance, not the volume, is the bottleneck (EBS-optimised bandwidth).
  • Pick a volume type from an exam scenario, and know which classic exam rule changed in 2025.
  • Use Multi-Attach correctly: io1/io2 only, one AZ, up to 16 Nitro instances, and a cluster-aware file system.
  • Explain what EBS encryption protects, how KMS envelope encryption works, how to encrypt an existing volume, and how to share an encrypted snapshot with another account.

#Why one kind of disk is not enough

Lesson 5.1 showed that an EBS volume is a network disk that lives in one Availability Zone and attaches to an instance. This lesson is about the second question you face when you create one: which volume type?

Workloads stress a disk in very different ways:

  • A database reads and writes thousands of small pieces (8 or 16 KiB pages) scattered all over the disk, and each user waits for every one of them. It needs many operations per second and low latency.
  • A log-processing or data warehouse job reads huge files from start to end. It hardly cares about single operations; it needs many megabytes per second.
  • An archive of old data is read once a month. It needs to be cheap.

No single disk is best at all three, so EBS offers SSD types tuned for operations and HDD types tuned for streaming, at very different prices.

#IOPS, throughput and latency

#Three numbers that describe a disk

MeasureWhat it countsUnitWho cares most
IOPSRead and write operations completed per secondoperations/sDatabases, boot volumes, anything with small random I/O
ThroughputData moved per secondMiB/sBig data, log processing, backups, media streaming
LatencyTime one operation takes from request to completionmilliseconds (ms) or microseconds (µs)Anything where a user or a transaction waits on each I/O

EBS measures I/O size in KiB and throughput in MiB/s (1 MiB = 1,024 KiB). For SSD volumes, AWS counts one I/O operation for every 256 KiB or less; a bigger I/O counts as several. For HDD volumes, one operation is counted for every 1 MiB or less.

Throughput (MiB/s) = IOPS × I/O size (KiB) ÷ 1,024

Every volume has two ceilings at once, one for IOPS and one for throughput, and you hit whichever comes first.

WorkloadIOPSI/O sizeThroughputWhat limits it
OLTP database on gp3 (baseline)3,00016 KiB3,000 × 16 ÷ 1,024 = 46.9 MiB/sIOPS (well under 125 MiB/s)
Same gp3, analytics query with 64 KiB reads3,000 wanted64 KiBwould be 187.5 MiB/sThroughput: 125 MiB/s ÷ 64 KiB = only 2,000 IOPS
io2 at 32,000 IOPS32,00016 KiB500 MiB/sNeither (io2 allows up to 4,000 MiB/s)
st1 sequential scan5001 MiB500 MiB/sBoth at once (st1 maximum)

The second row is the classic surprise: the volume “has 3,000 IOPS”, but with bigger I/Os it delivers only 2,000, because the throughput ceiling arrives first. The fix on gp3 is to provision more throughput, not more IOPS.

#Latency and queue depth

How many IOPS one application can actually drive also depends on latency and on how many I/Os it keeps in flight at once, the queue depth:

IOPS ≈ queue depth ÷ latency (in seconds)
  • A single-threaded program that waits for each write (queue depth 1) on a volume with 1 ms latency can do at most 1 ÷ 0.001 = 1,000 IOPS, however many IOPS you provisioned.
  • At 0.5 ms (io2 Block Express) the same program reaches about 2,000 IOPS.
  • To use 16,000 provisioned IOPS at 1 ms, the application needs about 16 I/Os in flight.

This is why a database transaction log, which writes one record and waits for it, benefits from lower latency more than from a higher IOPS number. CloudWatch shows the queue as VolumeQueueLength.

#Random versus sequential: SSD versus HDD

  • An SSD has no moving parts. Reaching block 1 or block 9,000,000 costs the same, so it is great at small random I/O: high IOPS, low latency.
  • An HDD has a spinning platter and a moving head. Every jump to a new place costs a seek, so random I/O is slow. Reading long sequential runs is efficient, so HDDs give good throughput per dollar for streaming work.

EBS turns this into two families: SSD types defined mainly by IOPS, HDD types defined by throughput.

#The SSD families

#gp2: performance that grows with size

gp2 is the older General Purpose SSD. Its performance is tied to its size:

  • Baseline: 3 IOPS per GiB, at least 100 IOPS (volumes of 33.33 GiB or less) and at most 16,000 IOPS (reached at 5,334 GiB).
  • Throughput: up to 128 MiB/s for volumes of 170 GiB or less, up to 250 MiB/s from 334 GiB.
  • Size: 1 GiB to 16 TiB. Single-digit millisecond latency.

Because small volumes would be painfully slow, gp2 volumes smaller than 1 TiB can burst to 3,000 IOPS using a credit bucket:

  1. Every volume starts with a full bucket of 5.4 million I/O credits (enough for a fast boot).
  2. When the volume does less than its baseline, it earns credits at its baseline rate (3 credits per GiB per second), up to the 5.4 million cap.
  3. When it does more than its baseline, it spends credits at (burst IOPS − baseline IOPS) per second.
  4. When the bucket is empty, the volume drops to its baseline. Nothing breaks, it just gets slow.
Burst duration = credit balance ÷ (burst IOPS − baseline IOPS)
gp2 sizeBaselineBurst from a full bucket at 3,000 IOPSRefill an empty bucket
20 GiB100 IOPS5,400,000 ÷ 2,900 ≈ 1,862 s (31 min)54,000 s (15 h)
100 GiB300 IOPS5,400,000 ÷ 2,700 = 2,000 s (33 min)18,000 s (5 h)
750 GiB2,250 IOPS5,400,000 ÷ 750 = 7,200 s (2 h)2,400 s (40 min)
1,000 GiB and more3,000+ IOPSNever needs to burst: baseline ≥ burst level—

That is why small gp2 volumes run out: a 100 GiB database volume flies for half an hour after a busy period starts, then falls to 300 IOPS, a tenth of the speed, and stays there until the load drops for hours. CloudWatch shows the remaining credits as BurstBalance (a percentage). The old fix was to make the volume bigger just to get IOPS, paying for storage you did not need.

gp2 credits vs gp3 baseline, one busy hour

Dashed: IOPS the database asks for. Solid: IOPS the volume delivers. Green strip: the gp2 credit bucket.

Scenario

Minute

0

Asked

3,000

Delivered

3,000

Credits left

97%

08751,7502,6253,5000102030405060baseline%
DeliveredAskedCredits left
Step 1 of 5
1

A 100 GiB gp2 volume: baseline 3 × 100 = 300 IOPS. It starts with a full bucket of 5.4 million credits. A busy period begins and the database asks for 3,000 IOPS.

#gp3: the default General Purpose SSD

gp3 removes the link between size and speed:

  • Baseline 3,000 IOPS and 125 MiB/s on every volume, whatever its size, included in the price. No credits, no burst: it sustains its provisioned performance all the time.
  • You can provision more IOPS and throughput separately from size: up to 80,000 IOPS (at most 500 IOPS per GiB, so 80,000 needs at least 160 GiB) and up to 2,000 MiB/s (at most 0.25 MiB/s per provisioned IOPS, so 2,000 MiB/s needs at least 8,000 IOPS).
  • Size: 1 GiB to 64 TiB. Single-digit millisecond latency, 99.8–99.9% durability.
  • About 20% cheaper per GiB than gp2. The console now offers gp3 by default.

These limits were raised in September 2025. Before that, gp3 stopped at 16,000 IOPS, 1,000 MiB/s and 16 TiB, and many exam questions and study notes still use those numbers.

#io1 and io2 Block Express: Provisioned IOPS SSD

Provisioned IOPS volumes are for workloads where storage performance must be high, consistent and predictable. You choose the IOPS you want and pay for them.

io2 Block Expressio1 (older)
Size4 GiB – 64 TiB4 GiB – 16 TiB
Max IOPS256,00064,000
IOPS per GiBup to 1,000:1 (256,000 needs 256 GiB)up to 50:1 (64,000 needs 1,280 GiB)
Max throughput4,000 MiB/s1,000 MiB/s
LatencySub-millisecond: average under 500 µs for 16 KiB I/O, far fewer slow outliersDepends on workload
Durability99.999% (1 failure per 100,000 volumes a year)99.8–99.9%
Multi-AttachYesYes
  • Since April 2025 every io2 volume is io2 Block Express; there is no separate “io2 classic” any more.
  • The highest numbers need a Nitro-based instance. Other instance types can attach volumes provisioned up to 64,000 IOPS but achieve at most 32,000.
  • io2 gives better durability and more IOPS per GiB for the same price per IOPS as io1, so AWS recommends io2 over io1 for new volumes.

When do you need io2 instead of gp3?

  • You need more than 80,000 IOPS or more than 2,000 MiB/s on one volume.
  • You need consistent sub-millisecond latency (gp3 is single-digit milliseconds).
  • You need 99.999% durability for mission-critical data (large Oracle or SQL Server databases).
  • You need Multi-Attach.

#The HDD families: st1 and sc1

st1 (Throughput Optimised HDD)sc1 (Cold HDD)
ForFrequently accessed, large, sequential data: big data, data warehouses, log processing, ETL, KafkaInfrequently accessed data where the lowest storage cost matters
Size125 GiB – 16 TiB125 GiB – 16 TiB
Baseline throughput40 MiB/s per TiB12 MiB/s per TiB
Burst throughput250 MiB/s per TiB80 MiB/s per TiB
Maximum500 MiB/s, 500 IOPS (1 MiB I/O)250 MiB/s, 250 IOPS (1 MiB I/O)
Boot volumeNoNo
Multi-AttachNoNo
  • Both use a throughput credit bucket, like gp2 but counted in MiB/s. A full bucket holds enough for a full scan of the volume.
  • A worked example: a 5 TiB st1 volume scanned end to end at 500 MiB/s takes 5 × 1,048,576 MiB ÷ 500 MiB/s ≈ 10,486 s, about 2.9 hours. The same scan on sc1 at 250 MiB/s takes about 5.8 hours.
  • Small random I/O is a disaster on HDD: every I/O of 1 MiB or less is charged as a full 1 MiB credit (sequential I/Os are merged into 1 MiB blocks first, random ones cannot be). A database doing 4 KiB random reads on st1 gets at most about 500 operations per second, which is 2 MiB/s of useful data.
  • sc1 is “cold”, not an archive: it is still a block device you mount and read. For true archives use S3 Glacier storage classes (chapter on S3).

#Which types can be boot volumes?

A boot (root) volume holds the operating system, which reads many small files at random during start-up: an SSD job.

  • Can boot: gp3, gp2, io2, io1 (and the previous-generation magnetic standard type).
  • Cannot boot: st1, sc1, and any volume with Multi-Attach enabled.

#The instance is half of the pipe

An EBS volume talks to its instance over the network, through the instance’s dedicated EBS bandwidth (current instance types are EBS-optimised by default, at no extra charge, so storage traffic does not compete with application traffic). That bandwidth is set by the instance type, and it has its own IOPS and throughput limits.

The speed you get is the lower of the two:

Real performance = min(volume limits, instance EBS limits)

Real numbers for one instance family (m7i, 16 KiB I/O for IOPS, 128 KiB I/O for throughput):

InstanceBaseline EBS IOPSBaseline EBS throughputBurst
m7i.large3,60081.25 MB/s40,000 IOPS / 1,250 MB/s for 30 min a day
m7i.4xlarge20,000625 MB/s40,000 IOPS / 1,250 MB/s for 30 min a day
m7i.8xlarge40,0001,250 MB/snone needed
m7i.48xlarge240,0005,000 MB/snone needed

So a 64,000 IOPS io2 volume attached to an m7i.large runs at about 3,600 IOPS once the instance’s own burst is used up. You paid for 64,000 provisioned IOPS and get one-eighteenth. The fix is a bigger instance (or a family with more EBS bandwidth), not a faster volume. Note also that several volumes on one instance share that instance limit.

Volume limits, instance limits, I/O size

The application gets the lowest of several ceilings. Watch which one bites in each case.

Scenario

Database
Instance EBS linkEBS-optimisedm7i.8xlarge
EBS volumeio2
CloudWatch
io2 · 32,000 IOPS
Step 1 of 3
1

An io2 volume provisioned with 32,000 IOPS, attached to an m7i.8xlarge, whose EBS link carries 40,000 IOPS and 1,250 MB/s.

#Choosing a volume type

#Decision table

The scenario saysChooseWhy
Boot volume, web server, dev/test, most applications, small or medium databasegp33,000 IOPS and 125 MiB/s included, cheapest SSD
“Increase IOPS without increasing storage size”, “decouple IOPS from size”, “save cost versus gp2”gp3IOPS and throughput are provisioned independently of size
Mission-critical database, sub-millisecond latency, 99.999% durability, more than 80,000 IOPS or 2,000 MiB/sio2 Block ExpressHighest IOPS, lowest latency, highest durability
One volume shared by several instances in one AZio2 (or io1) with Multi-AttachThe only types that support it
Big data, data warehouse, log processing, ETL, large sequential reads, cost-effectivest1High throughput per dollar
Infrequently accessed data, lowest cost per GiB, still block storagesc1Cheapest EBS type
Temporary data, cache, scratch, highest IOPS, data may be lostInstance store (lesson 5.3)Physically attached, but not persistent
Files shared by many instances across AZsEFS (lesson 5.4)A network file system, not a block volume

Which volume fits this workload?

Describe the I/O, pick an instance, and see what each volume type would need, which ones cannot do it at all, and where the instance becomes the bottleneck.

I/O size
Operations per second
Access pattern
Needs sub-millisecond latency
Instance

Needed throughput: 10,000 × 16 KiB ÷ 1,024 = 156 MiB/s

  • gp3★ best fit: provision 10,000 IOPS, 157 MiB/s (any size ≥ 20 GiB)
  • io2provision 10,000 IOPS (size ≥ 10 GiB), sub-ms latency
  • gp2works only at 3,334 GiB (3 IOPS/GiB); gp3 is cheaper
  • st1random: each I/O costs 1 MiB, so at most 500 operations/s
  • sc1random: each I/O costs 1 MiB, so at most 250 operations/s
i

gp3 carries it: provision IOPS and throughput for the workload and pay for storage only as big as the data. m7i.4xlarge has 20,000 IOPS / 625 MB/s of baseline EBS bandwidth, enough for this load.

#What it costs: a worked comparison

AWS’s own pricing examples use these rates (they vary by Region): gp2 $0.10 per GB-month; gp3 $0.08 per GB-month plus $0.005 per IOPS-month above 3,000; io2 $0.125 per GB-month plus $0.065 per IOPS-month (first 32,000); st1 $0.045; sc1 $0.015.

A database needs 1,000 GiB and 10,000 IOPS sustained:

OptionHowMonthly cost
gp210,000 ÷ 3 = 3,334 GiB just to reach the IOPS3,334 × 0.10 ≈ $333
gp31,000 GiB + 7,000 extra IOPS80 + 35 = $115
io21,000 GiB + 10,000 IOPS125 + 650 = $775

gp3 wins unless the workload needs what only io2 gives (latency, durability, Multi-Attach, more than 80,000 IOPS).

#Changing your mind later: Elastic Volumes

You do not have to get it right on day one. With Elastic Volumes (modify-volume, covered in lesson 5.1) you can change a volume’s type, size, IOPS and throughput while it is attached and in use, for example gp2 → gp3 with no downtime. Remember the limits: size can only grow, you then extend the file system yourself, and you must wait for a modification to finish (and at least 6 hours) before modifying the same volume again. st1 and sc1 cannot be smaller than 125 GiB, so a small volume cannot become one of them without growing.

Self-checkQuestion

A 100 GiB gp2 volume holds a reporting database. Every morning queries are fast for about half an hour, then everything becomes roughly ten times slower until the afternoon. the CloudWatch burst balance metric is at 0%. What is the most cost-effective fix?

#Multi-Attach: one volume, several instances

Normally an EBS volume is attached to one instance at a time. Multi-Attach lets a single volume be attached to several instances at once, each with full read and write access. It exists for clustered applications that must share one block device, such as a database cluster with shared storage or a failover pair that must take over the same disk instantly.

#The rules

  • Only io1 and io2 (Provisioned IOPS SSD). Not gp2, gp3, st1 or sc1. Windows instances support it on io2 only.
  • Same Availability Zone: the volume and every instance must be in the volume’s AZ.
  • Up to 16 instances, all built on the Nitro System.
  • Not a boot volume, and Multi-Attach cannot be enabled during instance launch. It is enabled when you create the volume, or later while it is detached.
  • The instances share the volume’s provisioned IOPS; CloudWatch metrics are aggregated across all of them.
  • No extra charge beyond the io1/io2 price.
  • If the volume has a problem at the EBS layer, every attached instance loses it at once, so Multi-Attach is not a substitute for a second copy of the data.

#Why the file system matters

Multi-Attach shares raw blocks, nothing more. EBS does not coordinate who writes what. Ordinary file systems such as ext4 and XFS assume they are the only one writing: each instance caches the file system’s metadata (which blocks are free, which file owns which block) in its own memory.

What goes wrong with ext4 on two instances:

  1. Instance A sees block 5,000 as free and writes file a.log there. It updates the free-block list in its own cache.
  2. Instance B, with its own stale cache, also sees block 5,000 as free and writes b.log there.
  3. Both flush their metadata. One overwrites the other’s records. The result is silent data corruption, files with mixed contents and a damaged file system.

The fix is a cluster-aware file system such as GFS2 or OCFS2, which runs a distributed lock manager so that only one node changes a given piece of metadata at a time, or an application that manages the raw block device itself and orders its own writes. io1/io2 Multi-Attach volumes also support NVMe reservations for I/O fencing: a cluster can lock out a node that has failed but may still try to write.

Multi-Attach: one io2 volume, several instances

EBS shares the blocks. It does not decide who writes what: that is the file system’s job.

Scenario

us-east-1
us-east-1a
us-east-1b
node-1GFS2
node-2GFS2
node-3GFS2
io2 volumeMulti-Attach
Step 1 of 4
1

An io2 volume created with Multi-Attach enabled, attached to three Nitro instances in its own AZ. Each one has full read and write access to the same blocks.

#EBS encryption

#What is encrypted

When you create an encrypted EBS volume and attach it to an instance, all of this is encrypted:

  • Data at rest inside the volume.
  • All data moving between the instance and the volume (data in transit on the EBS network path).
  • All snapshots created from the volume.
  • All volumes created from those snapshots.

Encryption happens on the servers that host your instances, in the Nitro hardware, using AES-256. Your operating system sees an ordinary disk; you install nothing and change nothing in the application. The effect on IOPS and latency is minimal, and all current instance types support it. You can attach encrypted and unencrypted volumes to the same instance.

What it does not cover: data your application sends over the network to anything else (use TLS for that), and data after your application reads it into memory.

#KMS keys: AWS managed or customer managed

EBS uses AWS KMS keys:

AWS managed key aws/ebsCustomer managed key
Created byEBS, automatically, one per RegionYou
CostNo monthly key chargeMonthly key charge plus API requests
Key policyFixed by AWS; you cannot edit itYou write it: who can use, manage, rotate, disable the key
RotationAutomatic (yearly)You choose (automatic rotation can be turned on)
Share encrypted snapshots with other accountsNoYes, by allowing those accounts in the key policy
Disable or schedule deletionNoYes

#How it works: envelope encryption with a data key

EBS does not send your disk’s data to KMS. It uses envelope encryption:

  1. When the encrypted volume is created, EC2 asks KMS for a new data key (a DEK; the API is GenerateDataKeyWithoutPlaintext). KMS generates a unique data key, encrypts it with your KMS key, and returns only the encrypted copy. EBS stores that encrypted data key with the volume’s metadata.
  2. When you attach the volume, EC2 asks KMS to decrypt the data key (CreateGrant, then Decrypt). This is the moment IAM and the key policy are checked.
  3. KMS returns the plaintext data key to the Nitro hardware of the host. It stays only in that hardware’s memory, for as long as the volume is attached, and encrypts and decrypts every block.
  4. Snapshots of the volume, and new volumes from those snapshots with the same KMS key, reuse that data key.

That last point is real behaviour: if you disable a KMS key, volumes already attached keep working, because the data key is already in the Nitro hardware. After the volume is detached, it cannot be attached again until the key is usable again.

#Encryption by default

EBS encryption by default is an account setting per Region. Once it is on:

  • Every new volume and every snapshot copy in that Region is encrypted, using the default key (aws/ebs, or a customer managed key you choose with modify-ebs-default-kms-key-id).
  • Volumes created from unencrypted snapshots are encrypted too.
  • Existing volumes and snapshots are not changed.
  • You cannot opt out for an individual volume in that Region.

It is the simplest way to make sure nobody forgets, and it also satisfies features that need an encrypted root, such as hibernation (lesson 4.5).

#Encrypting an existing unencrypted volume

You cannot switch encryption on for an existing volume or snapshot. The path goes through a snapshot:

  1. 1. Snapshot the unencrypted volume

    create-snapshot. The snapshot is unencrypted, like its source.

  2. 2. Copy the snapshot with encryption on

    copy-snapshot --encrypted --kms-key-id …. The copy is encrypted. (Shortcut: you can also skip the copy and create an encrypted volume directly from the unencrypted snapshot with create-volume --encrypted.)

  3. 3. Create a new volume from the encrypted snapshot

    create-volume, in the same AZ as the instance. Every volume created from an encrypted snapshot is encrypted.

  4. 4. Swap the volumes

    Stop the instance (for a root volume) or unmount the file system (for a data volume), detach the old volume, attach the new one with the same device name, and start or mount again. Check the data, then delete the old volume and the unencrypted snapshot.

The same snapshot-copy trick changes the KMS key of an encrypted volume (copy with a different key). A copy to a new key is a full copy, not incremental, so it costs more snapshot storage.

There is no way back: you cannot remove encryption from an encrypted volume or snapshot, and every volume or copy made from an encrypted snapshot is encrypted. To get unencrypted data you would have to copy the files at the operating-system level onto a new unencrypted volume.

#Sharing encrypted snapshots with another account

  • Snapshots encrypted with the AWS managed key aws/ebs cannot be shared: the other account can never use that key.
  • To share, the snapshot must be encrypted with a customer managed key. If it is not, first copy it and re-encrypt it with one.
  • Share the snapshot (modify-snapshot-attribute … --user-ids) and allow the other account in the key policy (permissions such as kms:DescribeKey, kms:CreateGrant, kms:Decrypt, kms:ReEncrypt*, kms:GenerateDataKey*).
  • Best practice for the receiving account: copy the shared snapshot and re-encrypt it with its own key, so it no longer depends on your key.
  • Encrypted snapshots can never be public. Snapshots and KMS keys are Regional: to use one in another Region, copy the snapshot there with a key from that Region.

EBS encryption with KMS

KMS never sees your blocks. It only protects the data key that the Nitro hardware uses.

Scenario

YouAWS CLI
EC2 / EBS
KMS
Nitro host
Partner account
create-volume --encrypted
Step 1 of 7
1

You create an encrypted volume and choose a KMS key: the AWS managed aws/ebs key, or a customer managed key.

#What goes wrong

SymptomLikely causeFix
Fast for 30 minutes, then about 10× slower; BurstBalance at 0%Small gp2 volume out of creditsMove to gp3 (Elastic Volumes) and provision the IOPS
Provisioned 64,000 IOPS, getting a few thousandInstance EBS bandwidth is lower than the volumeBigger instance or one with more EBS bandwidth
gp3 shows fewer IOPS than provisioned on large readsThroughput ceiling reached first (IOPS × I/O size)Provision more throughput (up to 2,000 MiB/s)
High latency with low IOPS, VolumeQueueLength near 0Application is single-threaded, queue depth 1More parallel I/O, or io2 for lower latency
st1 database is crawlingSmall random I/O on HDD, each charged as 1 MiBgp3 or io2
Two instances sharing an io2 volume see corrupted filesext4/XFS on a Multi-Attach volumeCluster file system (GFS2, OCFS2) or a cluster-aware application
create-volume from an encrypted snapshot without encryption still comes back encryptedEncryption cannot be removedExpected behaviour
Partner account cannot use your shared encrypted snapshotEncrypted with aws/ebs, or key policy does not allow themRe-encrypt with a customer managed key and grant the account
Encrypted volume will not attach after maintenanceKMS key disabled or scheduled for deletionRe-enable the key (cancel deletion)

#How it is used in system design

  • Default to gp3 for boot and general data volumes, size it for the data, and provision IOPS and throughput for the workload. Audit old gp2 volumes; moving them to gp3 is a live, cost-saving change.
  • Self-managed databases on EC2: gp3 for most, io2 Block Express when latency, durability or more than 80,000 IOPS matter. Size the instance for the EBS bandwidth too. Managed RDS uses the same volume types underneath.
  • Big data on EC2 (Hadoop, Kafka, log pipelines): st1 for large sequential data that must persist, instance store for scratch and shuffle space.
  • Beyond one volume: if one volume is not enough, several volumes can be striped with RAID 0 inside the operating system to add their IOPS and throughput (still capped by the instance). RAID 5/6 is not recommended on EBS because parity writes eat IOPS; EBS already replicates each volume inside its AZ.
  • High availability: Multi-Attach helps clustered software inside one AZ; it does not protect against an AZ failure. For that, replicate at the application level (database replicas in another AZ) or use a multi-AZ service.
  • Security baseline: turn on encryption by default in every Region you use (often enforced across an organisation), use customer managed keys where you need key policies, cross-account sharing or the ability to revoke access.

#Try it yourself

# 1. Create a gp3 volume with more IOPS and throughput than the baseline, encrypted
aws ec2 create-volume --availability-zone us-east-1a --volume-type gp3 \
  --size 200 --iops 12000 --throughput 500 --encrypted \
  --tag-specifications 'ResourceType=volume,Tags=[{Key=Name,Value=db-data}]'

# 2. An io2 Block Express volume with Multi-Attach (attach it to Nitro instances in us-east-1a)
aws ec2 create-volume --availability-zone us-east-1a --volume-type io2 \
  --size 500 --iops 50000 --multi-attach-enabled
aws ec2 attach-volume --volume-id $VOL --instance-id $NODE1 --device /dev/sdf
aws ec2 attach-volume --volume-id $VOL --instance-id $NODE2 --device /dev/sdf

# 3. Try Multi-Attach on gp3: rejected (only io1/io2 support it)
aws ec2 create-volume --availability-zone us-east-1a --volume-type gp3 --size 50 --multi-attach-enabled

# 4. Move an old gp2 volume to gp3 live, then watch the modification
aws ec2 modify-volume --volume-id $OLD_GP2 --volume-type gp3 --iops 6000 --throughput 250
aws ec2 describe-volumes-modifications --volume-ids $OLD_GP2

# 5. Watch a gp2 volume's credits (percent) in CloudWatch
aws cloudwatch get-metric-statistics --namespace AWS/EBS --metric-name BurstBalance \
  --dimensions Name=VolumeId,Value=$OLD_GP2 --statistics Minimum \
  --start-time 2026-10-24T00:00:00Z --end-time 2026-10-25T00:00:00Z --period 300

# 6. Check the instance's EBS limits (baseline and maximum IOPS / throughput)
aws ec2 describe-instance-types --instance-types m7i.large m7i.8xlarge \
  --query "InstanceTypes[].[InstanceType,EbsInfo.EbsOptimizedInfo.BaselineIops,EbsInfo.EbsOptimizedInfo.MaximumIops,EbsInfo.EbsOptimizedInfo.BaselineThroughputInMBps]"

# 7. Encryption by default in this Region, and its key
aws ec2 enable-ebs-encryption-by-default
aws ec2 get-ebs-encryption-by-default
aws ec2 get-ebs-default-kms-key-id

# 8. Encrypt an existing unencrypted volume
SNAP=$(aws ec2 create-snapshot --volume-id $PLAIN_VOL --query SnapshotId --output text)
aws ec2 wait snapshot-completed --snapshot-ids $SNAP
ENC=$(aws ec2 copy-snapshot --source-region us-east-1 --source-snapshot-id $SNAP \
  --encrypted --kms-key-id alias/app-ebs --query SnapshotId --output text)
aws ec2 wait snapshot-completed --snapshot-ids $ENC
NEW=$(aws ec2 create-volume --snapshot-id $ENC --availability-zone us-east-1a \
  --volume-type gp3 --query VolumeId --output text)
aws ec2 stop-instances --instance-ids $ID            # if it is the root volume
aws ec2 detach-volume --volume-id $PLAIN_VOL
aws ec2 attach-volume --volume-id $NEW --instance-id $ID --device /dev/xvda
aws ec2 start-instances --instance-ids $ID

# 9. Share an encrypted snapshot (customer managed key) with another account
aws ec2 modify-snapshot-attribute --snapshot-id $ENC --attribute createVolumePermission \
  --operation-type add --user-ids 111122223333
# ...and add account 111122223333 to the key policy of alias/app-ebs.

#Summary

Key takeaways

  • Throughput = IOPS × I/O size. Every volume has an IOPS ceiling and a throughput ceiling; you hit whichever comes first. Latency and queue depth decide how many IOPS one application can drive.
  • gp2: 3 IOPS/GiB (100 to 16,000), volumes under 1 TiB burst to 3,000 IOPS on a 5.4 million credit bucket; a 100 GiB volume bursts about 33 minutes, then drops to 300 IOPS.
  • gp3 (the default): 3,000 IOPS and 125 MiB/s included at any size, provision up to 80,000 IOPS and 2,000 MiB/s independently of size, up to 64 TiB, no credits, about 20% cheaper than gp2.
  • io2 Block Express: up to 256,000 IOPS, 1,000 IOPS/GiB, 4,000 MiB/s, 64 TiB, sub-millisecond latency, 99.999% durability. io1 is the older version (64,000 IOPS, 50:1). Both support Multi-Attach.
  • st1 (big data, logs, warehouses, up to 500 MiB/s) and sc1 (cold, cheapest, up to 250 MiB/s): HDD, 125 GiB minimum, cannot boot, bad at small random I/O.
  • Boot volumes: gp3, gp2, io2, io1. Not st1, sc1 or Multi-Attach volumes.
  • Real performance is min(volume, instance EBS bandwidth): a fast volume on a small instance is still slow.
  • Multi-Attach: io1/io2 only, same AZ, up to 16 Nitro instances, not a boot volume, needs a cluster-aware file system (GFS2, OCFS2); ext4/XFS will corrupt data.
  • Encryption: data at rest, data in transit to the instance, snapshots, and volumes from them; AES-256 with a KMS-protected data key held in Nitro hardware; minimal performance impact; encryption by default per Region.
  • Encrypt an existing volume via snapshot → encrypted copy → new volume → swap. No way back to unencrypted. Share encrypted snapshots only with a customer managed key plus key policy; aws/ebs cannot be shared.