<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Muhammad Umar</title>
    <description>The latest articles on DEV Community by Muhammad Umar (@devopswithumar).</description>
    <link>https://dev.to/devopswithumar</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4225969%2Fbb028841-536e-4488-87d0-5997447e819e.jpg</url>
      <title>DEV Community: Muhammad Umar</title>
      <link>https://dev.to/devopswithumar</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/devopswithumar"/>
    <language>en</language>
    <item>
      <title>gp2 vs gp3: switch EBS volumes, save 20%, no downtime</title>
      <dc:creator>Muhammad Umar</dc:creator>
      <pubDate>Wed, 04 Nov 2026 10:42:44 +0000</pubDate>
      <link>https://dev.to/devopswithumar/gp2-vs-gp3-switch-ebs-volumes-save-20-no-downtime-5d2n</link>
      <guid>https://dev.to/devopswithumar/gp2-vs-gp3-switch-ebs-volumes-save-20-no-downtime-5d2n</guid>
      <description>&lt;p&gt;In short:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;gp3 costs $0.08 per GB-month against $0.10 for gp2, and includes 3,000 IOPS and 125 MiB/s at any size.&lt;/li&gt;
&lt;li&gt;You can switch a volume from gp2 to gp3 while it stays attached and in use.&lt;/li&gt;
&lt;li&gt;gp2 volumes of 334 GiB and up lose throughput, and those over 1 TiB lose IOPS, unless you set both on gp3.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;gp2 vs gp3 has a short answer: &lt;strong&gt;gp3 is the better EBS volume for almost every workload, and it costs 20% less.&lt;/strong&gt; gp3 storage is $0.08 per GB-month against $0.10 for gp2, and every gp3 volume gets 3,000 IOPS and 125 MiB/s included, whatever its size. You can switch a live volume in place, without stopping the instance.&lt;/p&gt;

&lt;p&gt;Most AWS accounts I review still have gp2 volumes. They were created by old launch templates, old Terraform modules, or an EKS cluster's default StorageClass, and nobody went back. This post shows how to find them, switch them safely, and stop new ones from appearing.&lt;/p&gt;

&lt;h2&gt;
  
  
  gp2 vs gp3 at a glance
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Feature&lt;/th&gt;
&lt;th&gt;gp2&lt;/th&gt;
&lt;th&gt;gp3&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Price (us-east-1)&lt;/td&gt;
&lt;td&gt;$0.10 per GB-month&lt;/td&gt;
&lt;td&gt;$0.08 per GB-month&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Baseline IOPS&lt;/td&gt;
&lt;td&gt;3 per GiB (100 minimum)&lt;/td&gt;
&lt;td&gt;3,000 at any size&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Burst&lt;/td&gt;
&lt;td&gt;Up to 3,000 IOPS on volumes under 1 TiB, while credits last&lt;/td&gt;
&lt;td&gt;No burst needed, performance is constant&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum IOPS&lt;/td&gt;
&lt;td&gt;16,000&lt;/td&gt;
&lt;td&gt;80,000&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Throughput&lt;/td&gt;
&lt;td&gt;128 to 250 MiB/s, depending on size&lt;/td&gt;
&lt;td&gt;125 MiB/s included, up to 2,000 MiB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Extra performance&lt;/td&gt;
&lt;td&gt;Only by making the volume bigger&lt;/td&gt;
&lt;td&gt;Paid separately: $0.005 per IOPS, $0.04 per MiB/s&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The important difference is the last row. On gp2, IOPS are tied to size: a 100 GiB gp2 volume gets 300 baseline IOPS, and the only way to get more is to buy more disk. On gp3, size and performance are separate, so you pay for the storage you need and add performance only if you need it.&lt;/p&gt;

&lt;p&gt;gp3 limits went up in September 2025: a gp3 volume can now be up to 64 TiB, with 80,000 IOPS and 2,000 MiB/s (&lt;a href="https://aws.amazon.com/about-aws/whats-new/2025/09/amazon-ebs-size-provisioned-performance-gp3-volumes" rel="noopener noreferrer"&gt;AWS announcement&lt;/a&gt;).&lt;/p&gt;

&lt;h2&gt;
  
  
  What gp2 to gp3 saves: real numbers
&lt;/h2&gt;

&lt;p&gt;Here is what the switch does for typical volumes in us-east-1:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Volume&lt;/th&gt;
&lt;th&gt;gp2 per month&lt;/th&gt;
&lt;th&gt;gp3 per month&lt;/th&gt;
&lt;th&gt;Saving&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;10 root volumes of 30 GiB&lt;/td&gt;
&lt;td&gt;$30&lt;/td&gt;
&lt;td&gt;$24&lt;/td&gt;
&lt;td&gt;$6 (20%), and 3,000 IOPS each instead of 100&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;500 GiB database volume&lt;/td&gt;
&lt;td&gt;$50&lt;/td&gt;
&lt;td&gt;$40 (+$5 to keep 250 MiB/s)&lt;/td&gt;
&lt;td&gt;$5 to $10, and 3,000 IOPS instead of 1,500&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;2,000 GiB volume, matching gp2 performance&lt;/td&gt;
&lt;td&gt;$200&lt;/td&gt;
&lt;td&gt;$180&lt;/td&gt;
&lt;td&gt;$20 (10%)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The 2,000 GiB row is the one to watch. A gp2 volume that size has 6,000 IOPS and 250 MiB/s. To match it on gp3 you pay for 3,000 extra IOPS ($15) and 125 extra MiB/s ($5) on top of $160 of storage. It is still cheaper, but only if you set those numbers. That is the mistake in the next section.&lt;/p&gt;

&lt;p&gt;Storage is rarely the biggest line on an AWS bill, but this is the safest saving there is: no code change, no restart, no risk. For the bigger wins, see &lt;a href="https://devopswithumar.com/blog/cut-your-aws-bill-quick-wins/" rel="noopener noreferrer"&gt;how to reduce your AWS bill&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The big-volume IOPS trap
&lt;/h2&gt;

&lt;p&gt;When you change a volume to gp3 without saying anything else, AWS gives it the gp3 baseline: 3,000 IOPS and 125 MiB/s.&lt;/p&gt;

&lt;p&gt;For IOPS that is more than gp2 gives any volume under 1 TiB. For throughput, and for very big volumes, it can be less:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A 2,000 GiB gp2 volume runs at 6,000 IOPS. Switched with defaults, it drops to 3,000.&lt;/li&gt;
&lt;li&gt;Any gp2 volume of 334 GiB or more delivers 250 MiB/s. Switched with defaults, it drops to 125 MiB/s.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Before you switch a large volume, check its baseline (size × 3, up to 16,000) and look at its real usage in CloudWatch (&lt;code&gt;VolumeReadOps&lt;/code&gt;, &lt;code&gt;VolumeWriteOps&lt;/code&gt;, &lt;code&gt;VolumeReadBytes&lt;/code&gt;, &lt;code&gt;VolumeWriteBytes&lt;/code&gt;). Then set &lt;code&gt;--iops&lt;/code&gt; and &lt;code&gt;--throughput&lt;/code&gt; to what it actually uses, not what gp2 happened to give it. Many big volumes use far less than their gp2 baseline, which makes the saving bigger.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 1: find every gp2 volume
&lt;/h2&gt;

&lt;p&gt;Volumes live in regions, so check them all. This lists every gp2 volume in the account with its region, size and state:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="k"&gt;for &lt;/span&gt;r &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="si"&gt;$(&lt;/span&gt;aws ec2 describe-regions &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Regions[].RegionName'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text&lt;span class="si"&gt;)&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;do
  &lt;/span&gt;aws ec2 describe-volumes &lt;span class="nt"&gt;--region&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="s2"&gt;"&lt;/span&gt; &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--filters&lt;/span&gt; &lt;span class="nv"&gt;Name&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;volume-type,Values&lt;span class="o"&gt;=&lt;/span&gt;gp2 &lt;span class="se"&gt;\&lt;/span&gt;
    &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'Volumes[].[VolumeId,Size,State]'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text |
    &lt;span class="nb"&gt;sed&lt;/span&gt; &lt;span class="s2"&gt;"s/^/&lt;/span&gt;&lt;span class="nv"&gt;$r&lt;/span&gt;&lt;span class="s2"&gt; /"&lt;/span&gt;
&lt;span class="k"&gt;done&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Volumes in the &lt;code&gt;available&lt;/code&gt; state are not attached to anything. Do not convert those: snapshot them and delete them instead, as explained in &lt;a href="https://devopswithumar.com/blog/aws-charges-billing-you-for-nothing/" rel="noopener noreferrer"&gt;3 hidden AWS charges&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: switch a volume from gp2 to gp3, live
&lt;/h2&gt;

&lt;p&gt;For a volume under 334 GiB, one command is enough:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 modify-volume &lt;span class="nt"&gt;--volume-id&lt;/span&gt; vol-0abc123def4567890 &lt;span class="nt"&gt;--volume-type&lt;/span&gt; gp3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a volume of 334 GiB or more, set the performance it needs (here, matching a 2,000 GiB gp2 volume):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 modify-volume &lt;span class="nt"&gt;--volume-id&lt;/span&gt; vol-0abc123def4567890 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--volume-type&lt;/span&gt; gp3 &lt;span class="nt"&gt;--iops&lt;/span&gt; 6000 &lt;span class="nt"&gt;--throughput&lt;/span&gt; 250
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then watch the progress:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws ec2 describe-volumes-modifications &lt;span class="nt"&gt;--volume-ids&lt;/span&gt; vol-0abc123def4567890 &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--query&lt;/span&gt; &lt;span class="s1"&gt;'VolumesModifications[].[ModificationState,Progress]'&lt;/span&gt; &lt;span class="nt"&gt;--output&lt;/span&gt; text
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The volume stays attached and keeps serving reads and writes while it changes. Small volumes finish in minutes; large ones can take hours. You can modify a volume up to four times in a rolling 24-hour window, each change after the previous one completes (&lt;a href="https://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifyVolume.html" rel="noopener noreferrer"&gt;ModifyVolume reference&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;Two habits make this boring:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Take a snapshot first if the volume holds anything you cannot rebuild. The change is safe, but a snapshot costs little and lets you sleep.&lt;/li&gt;
&lt;li&gt;Switch one non-production volume, watch it for a day, then do the rest.&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Step 3: switch gp2 to gp3 in Terraform
&lt;/h2&gt;

&lt;p&gt;If Terraform created the volume, change it in Terraform, or the next &lt;code&gt;terraform apply&lt;/code&gt; will switch it back.&lt;/p&gt;

&lt;p&gt;A standalone volume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_ebs_volume"&lt;/span&gt; &lt;span class="s2"&gt;"data"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;availability_zone&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"us-east-1a"&lt;/span&gt;
  &lt;span class="nx"&gt;size&lt;/span&gt;              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;500&lt;/span&gt;
  &lt;span class="nx"&gt;type&lt;/span&gt;              &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"gp3"&lt;/span&gt;
  &lt;span class="c1"&gt;# Only needed above the gp3 baseline of 3,000 IOPS and 125 MiB/s:&lt;/span&gt;
  &lt;span class="c1"&gt;# iops       = 6000&lt;/span&gt;
  &lt;span class="c1"&gt;# throughput = 250&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;An instance's root volume:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_instance"&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;ami&lt;/span&gt;           &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"ami-0123456789abcdef0"&lt;/span&gt;
  &lt;span class="nx"&gt;instance_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"t3.medium"&lt;/span&gt;

  &lt;span class="nx"&gt;root_block_device&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;volume_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"gp3"&lt;/span&gt;
    &lt;span class="nx"&gt;volume_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A launch template, so every new instance starts on gp3:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="nx"&gt;resource&lt;/span&gt; &lt;span class="s2"&gt;"aws_launch_template"&lt;/span&gt; &lt;span class="s2"&gt;"app"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;name_prefix&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"app-"&lt;/span&gt;

  &lt;span class="nx"&gt;block_device_mappings&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;device_name&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"/dev/xvda"&lt;/span&gt;
    &lt;span class="nx"&gt;ebs&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
      &lt;span class="nx"&gt;volume_type&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"gp3"&lt;/span&gt;
      &lt;span class="nx"&gt;volume_size&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;terraform plan&lt;/code&gt; and read it before you apply. A volume type change should show as &lt;strong&gt;update in-place&lt;/strong&gt;. If the plan says a resource will be &lt;strong&gt;replaced&lt;/strong&gt;, stop and find out why first: replacing an instance or a volume is not the same as modifying it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 4: EKS and Kubernetes volumes
&lt;/h2&gt;

&lt;p&gt;Older EKS clusters ship with a &lt;code&gt;gp2&lt;/code&gt; StorageClass as the default, so every new PersistentVolume is gp2. With the EBS CSI driver installed, add a gp3 StorageClass and make it the default:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;apiVersion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;storage.k8s.io/v1&lt;/span&gt;
&lt;span class="na"&gt;kind&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;StorageClass&lt;/span&gt;
&lt;span class="na"&gt;metadata&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gp3&lt;/span&gt;
  &lt;span class="na"&gt;annotations&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;storageclass.kubernetes.io/is-default-class&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;true"&lt;/span&gt;
&lt;span class="na"&gt;provisioner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;ebs.csi.aws.com&lt;/span&gt;
&lt;span class="na"&gt;parameters&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;gp3&lt;/span&gt;
&lt;span class="na"&gt;volumeBindingMode&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;WaitForFirstConsumer&lt;/span&gt;
&lt;span class="na"&gt;allowVolumeExpansion&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then remove the default annotation from the old gp2 class, so only one class is the default. Existing PersistentVolumes keep their EBS volume, so switch those with the same &lt;code&gt;aws ec2 modify-volume&lt;/code&gt; command from Step 2; the pods keep running. For more on keeping pods healthy, see &lt;a href="https://devopswithumar.com/blog/kubernetes-mistakes-crash-pods/" rel="noopener noreferrer"&gt;3 Kubernetes mistakes that crash your pods&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop new gp2 volumes from appearing
&lt;/h2&gt;

&lt;p&gt;Switching today's volumes is half the job. The other half is making sure next month's volumes are gp3:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Default EBS volume type in Terraform modules and launch templates&lt;/strong&gt;: set &lt;code&gt;gp3&lt;/code&gt; everywhere a volume type appears.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;EKS default StorageClass&lt;/strong&gt;: gp3, as above.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;A monthly check&lt;/strong&gt;: run the Step 1 loop, or add it to the routine in &lt;a href="https://devopswithumar.com/aws-cost-checklist/" rel="noopener noreferrer"&gt;the AWS cost checklist&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  gp2 vs gp3 checklist
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;List every gp2 volume in every region.&lt;/li&gt;
&lt;li&gt;Delete the unattached ones instead of converting them.&lt;/li&gt;
&lt;li&gt;Switch volumes under 334 GiB with one command.&lt;/li&gt;
&lt;li&gt;For volumes of 334 GiB and up, check real IOPS and throughput in CloudWatch, and set them on gp3.&lt;/li&gt;
&lt;li&gt;Change the type in Terraform too, and check the plan says update in-place.&lt;/li&gt;
&lt;li&gt;Make gp3 the default in launch templates, modules and the EKS StorageClass.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Want a rough number for your whole account first? The &lt;a href="https://devopswithumar.com/tools/aws-cost-calculator/" rel="noopener noreferrer"&gt;AWS cost savings calculator&lt;/a&gt; has gp2 as one of its checks. If you would rather have someone go through the account with you, the &lt;a href="https://devopswithumar.com/services/aws-cost-optimization/" rel="noopener noreferrer"&gt;AWS cost optimization&lt;/a&gt; review covers this and the bigger wins, or start with a &lt;a href="https://devopswithumar.com/checkup/" rel="noopener noreferrer"&gt;Free AWS Review&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Prices and limits are from the &lt;a href="https://aws.amazon.com/ebs/general-purpose/" rel="noopener noreferrer"&gt;Amazon EBS General Purpose volumes page&lt;/a&gt; and the &lt;a href="https://docs.aws.amazon.com/ebs/latest/userguide/general-purpose.html" rel="noopener noreferrer"&gt;EBS user guide&lt;/a&gt;, checked in November 2026. Prices vary slightly by region.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common questions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Is gp3 always cheaper than gp2?
&lt;/h3&gt;

&lt;p&gt;For almost every volume, yes. gp3 storage is 20% cheaper, and below 1 TiB you get more IOPS for free. Very large gp2 volumes need extra IOPS and throughput bought on gp3 to match, which narrows the saving, but it usually stays cheaper.&lt;/p&gt;

&lt;h3&gt;
  
  
  Do I need to stop my EC2 instance to change gp2 to gp3?
&lt;/h3&gt;

&lt;p&gt;No. On current-generation instance types you change the volume type while it stays attached and in use. The volume keeps serving reads and writes during the change.&lt;/p&gt;

&lt;h3&gt;
  
  
  How long does a gp2 to gp3 change take?
&lt;/h3&gt;

&lt;p&gt;It depends on the volume size and how busy it is: small volumes finish in minutes, large ones can take hours. You can keep using the volume the whole time.&lt;/p&gt;

&lt;h3&gt;
  
  
  Can I go back from gp3 to gp2?
&lt;/h3&gt;

&lt;p&gt;Yes, with the same modify-volume command. You can modify a volume up to four times in a rolling 24-hour window, once the previous change has completed.&lt;/p&gt;

&lt;h3&gt;
  
  
  What about Kubernetes volumes on EKS?
&lt;/h3&gt;

&lt;p&gt;Set a gp3 StorageClass as the default for new volumes, then switch existing volumes with the same AWS CLI command. The pods keep running.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;Originally published on &lt;a href="https://devopswithumar.com/blog/gp2-vs-gp3-ebs/" rel="noopener noreferrer"&gt;DevOps with Umar&lt;/a&gt;. I keep free browser tools for this kind of work there: an &lt;a href="https://devopswithumar.com/tools/aws-cost-calculator/" rel="noopener noreferrer"&gt;AWS savings estimator&lt;/a&gt;, a &lt;a href="https://devopswithumar.com/tools/cron-generator/" rel="noopener noreferrer"&gt;cron expression generator&lt;/a&gt; and more in &lt;a href="https://devopswithumar.com/tools/" rel="noopener noreferrer"&gt;the tools list&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>cloud</category>
      <category>terraform</category>
    </item>
  </channel>
</rss>
