Why Is Your AWS EC2 T3 Instance So Slow? CPU Credits & T3 Unlimited Explained
If your t3 instance suddenly got slow, open CloudWatch and look at two things: the instance's credit specification (Standard or Unlimited) and its CPUCreditBalance. If it's Standard and the balance is at zero, AWS has been lowering your CPU toward the baseline, and the fix is to switch to Unlimited or move to a bigger or fixed-performance instance. Here's the twist: a t3 launches in Unlimited mode by default, and Unlimited doesn't slow you down when credits hit zero. It borrows credits and bills you instead. So on a default t3, an empty balance usually means a bigger bill, not a slower server.
Jake sells phones and repairs screens, and his repair-booking page runs on a small t3 server he set up two years ago and mostly forgot about. One Saturday morning the page started taking eleven seconds to load. People who couldn't book walked next door, and by lunch he'd lost roughly $240 in screen repairs. He called Ethan, sure the server was "too small."
A note on the cast: Jake and Ethan are this blog's recurring teaching pair, a shop owner and his mentor, so read Jake's Saturday as an illustration and not as evidence. The steps below come from AWS's own documentation. Nobody has run them on your account, and I can't see your graphs, so the graphs are yours to read. Ethan's first reply is the useful part: "Before you pay for a bigger server, find out which kind of slow it is. There are three kinds, and only one of them is about credits."
The 60-second check: is it really CPU credits?
Two terms first, since you'll see them everywhere. CloudWatch is AWS's built-in monitoring service: it draws graphs of what your servers are doing. The AWS CLI (command line interface) is a small program where you type commands instead of clicking around the console. You can do everything below with either one.
- Find the credit mode. Open the EC2 console, choose Instances, and select the slow instance. On the Details tab, find Credit specification. It reads either
unlimitedorstandard. Prefer the command line? This does the same job:aws ec2 describe-instance-credit-specifications \ --instance-id i-1234567890abcdef0 \ --query InstanceCreditSpecifications[].CpuCredits \ --output text - Open the credit graphs. In the CloudWatch console, choose Metrics, select the EC2 namespace, then Per-Instance Metrics, and search for your instance ID.
- Graph these three:
CPUUtilization,CPUCreditBalanceandCPUCreditUsage. If the mode is Unlimited, addCPUSurplusCreditBalanceandCPUSurplusCreditsCharged. - Widen the time range to at least three days, so the graph shows a normal stretch before the slow one.
- Line up the moments. Did the credit balance reach zero at about the time the CPU line flattened? Remember that these credit metrics update every five minutes, so expect a slightly blocky picture.
Now read the result. Standard mode, balance at zero, and a CPU line that flattens near your size's baseline (Table 1 below has the numbers): that's the classic throttle, and Situation A is yours. Unlimited mode with a balance at zero: nothing is throttling you, and you should read Situation B. Credits healthy but the site still crawls: skip to Situation C.
♂️ Jake's Reality Check
"I sell phones. Do I really have to stare at graphs to find out why my own booking page is slow?"
The straight answer. Yes, once, for about ten minutes. After that you set an alarm (there's a section for it) and the graph comes to you. Guessing is the expensive option: resizing a server without reading the credit metrics can cost you money and leave the actual problem in place.
CPU credits explained, using a shop's cash drawer
Ethan explains it the way he'd explain it to a shopkeeper. "Picture a cash drawer that gets a few rupees dropped in every hour, automatically, whether or not anyone is at the counter. On a quiet afternoon it fills up. On a rush day you spend from it faster than it refills. When the drawer's empty, you can only spend as fast as the automatic drops arrive."
That's the whole system. Now the real words for each part.
⚡ MUST-READ EC2 PERFORMANCE & CPU GUIDES
- π ️ Fix AWS EC2 EBS Volume Stuck Attaching or In-Use Error
- π Fix AWS EC2 Instance Stuck in Stopping State Fast
- ⚠️ AWS EC2 InsufficientInstanceCapacity: Meaning & Workarounds
- π AWS Auto Scaling Guide: Managing Burstable Instance Fleets
- π₯️ Request GPU & vCPU Quotas for Burstable EC2 Workloads
vCPU. A virtual CPU: one processor thread that your instance gets to use. A t3.micro has 2 of them, a t3.xlarge has 4.
CPU credit. A unit of vCPU time. One credit equals one vCPU running flat out (100%) for one minute. AWS's documentation gives equivalent forms: one vCPU at 50% for two minutes, or two vCPUs at 25% for two minutes, are also one credit each.
Baseline utilization. The level of CPU use at which credits earned equal credits spent, so the balance neither grows nor shrinks. AWS's formula is: baseline % = (credits earned per hour ÷ number of vCPUs) ÷ 60. A t3.large earns 36 credits an hour and has 2 vCPUs, so (36 ÷ 2) ÷ 60 = 30%.
Earned, accrued and spent credits. An instance earns credits continuously while it's running, at millisecond resolution, so a short burst uses only a small fraction of one credit. When it uses less CPU than its baseline, the unspent credits pile up in its credit balance (accrued credits). When it uses more, it spends from that balance.
Accrual limit. The drawer has a lid. The balance can only hold the credits earned in 24 hours, and anything earned after that is discarded. So a t3.micro tops out at 288 credits. Credits sitting in a running instance never expire, but the drawer never holds more than a day's worth.
| Instance | vCPUs | Credits earned per hour | Max balance | Baseline (as read in CloudWatch) |
|---|---|---|---|---|
| t3.nano | 2 | 6 | 144 | 5% |
| t3.micro | 2 | 12 | 288 | 10% |
| t3.small | 2 | 24 | 576 | 20% |
| t3.medium | 2 | 24 | 576 | 20% |
| t3.large | 2 | 36 | 864 | 30% |
| t3.xlarge | 4 | 96 | 2,304 | 40% |
| t3.2xlarge | 8 | 192 | 4,608 | 40% |
Table 1 shows the T3 family, using the numbers in AWS's credit table. Read the last column carefully, because it's where most of the confusion lives. AWS's note under that table says a t3.large running exactly at baseline shows up as 30% in CloudWatch's CPU metric. So you compare the CloudWatch percentage directly to the baseline column. Don't double it because the instance has two vCPUs.
Jake: "So a t3.medium is only 'allowed' to average 20%? That sounds tiny."
Ethan: "It is tiny, and that's the point. Most servers sit idle most of the day. AWS's documentation describes T instances as built for workloads that are on average not busy: web servers, small databases, dev and test machines, code repositories. Averaging under 20% is normal for that crowd. If your average lives above it, you bought the wrong tool, and no setting will turn a screwdriver into a hammer."
Standard vs. Unlimited: two ways of running out
Every burstable instance runs in one of two credit modes, and what "out of credits" means depends entirely on which one.
Standard mode. The instance bursts above baseline by spending accrued credits. If it runs low, AWS's documentation says CPU is gradually lowered to the baseline level, so you don't fall off a cliff at the moment the balance hits zero. Once the balance is gone, the instance can't burst again until it earns more credits.
Unlimited mode. The instance spends accrued credits first. When they run out, it spends surplus credits, which is credit it borrows against future earnings. When CPU use falls back below baseline, the credits it earns pay down that surplus before the balance starts growing again. AWS averages this over a rolling 24-hour window: if your average CPU over that window stays at or below baseline, you pay nothing extra. If it stays above, you pay a flat extra rate per vCPU-hour for the excess.
What changed between generations
- Before: the older T2 family launches as Standard by default. T2 Standard also gets launch credits (30 per vCPU) so it can burst right after starting, and a stopped T2 loses all its credits.
- Now: T3, T3a, T4g and T8i launch as Unlimited by default. They get no launch credits, because they can burst from the first second, and their balance survives for seven days after a stop.
- What that means here: on a modern t3, "slow because credits ran out" is only possible if the instance is running as Standard. Someone (or some template) chose that.
Ethan: "I'll say the opinion out loud: for anything a customer touches, Unlimited is the sane default. A slow booking page costs Jake more in an hour than the surplus credits would in a month. Standard mode is for machines where a slowdown is annoying and nobody loses money."
Jake: "Then why would anyone pick Standard?"
Ethan: "Because Standard can never surprise you on the invoice. That's a real reason, if you have a hard budget and a job that can wait. There's also one case where you don't get to choose: T3 instances on a Dedicated Host, which is a physical server reserved for you alone, only run as Standard. Unlimited isn't supported there."
Which slow is yours? A symptom-first triage
Find the row that looks like your graphs. It saves you from reading the sections that aren't about you.
| What you see | Most likely meaning | Go to |
|---|---|---|
| Mode is standard, CPUCreditBalance at 0, CPU line flat near your baseline | The throttle. Credits ran out and CPU is held near baseline | Situation A |
| Mode is unlimited, balance at 0, CPUSurplusCreditBalance above 0, CPU high | Not throttled. The instance is spending borrowed credits | Situation B |
| Mode is unlimited, balance at 0, but CPU is nearly idle | Earned credits are still paying down old surplus. Not a fault | Situation B |
| Slow only for a while after launch or start, mode is standard | A Standard T3 gets no launch credits, or its balance expired after a long stop | Why Standard? |
| CPU low, credits healthy, pages still crawl | Memory, disk or network is the bottleneck | Situation C |
| Slow during heavy disk activity, gp2 BurstBalance low | The disk's own burst bucket is empty. A different credit system | Situation C |
Rows two and three are the reason this post exists. Most advice online treats "credit balance is zero" as a single diagnosis. On a modern t3 it can mean opposite things.
Reading your credit graph: two worked examples
The numbers on the graph come from simple arithmetic, and once you can do it yourself, the shapes stop being mysterious. AWS publishes the equations, and CloudWatch updates them every five minutes. Every example below is my own arithmetic on AWS's formulas, meant to teach the mechanics. It isn't a reading from anyone's real server.
Standard mode. The rule: new balance = previous balance + (credits earned per hour × 5/60) − credits used in the last five minutes. AWS's own example is a t3.nano, which earns 6 credits an hour, so 0.5 credits every five minutes. If it had 2 credits five minutes ago and spent 1, the new balance is 2 + (0.5 − 1) = 1.5. If it keeps spending 1 credit per interval, the next readings are 1.0, then 0.5, then 0. That's fifteen more minutes before the drawer is empty, and from there AWS holds the instance near its 5% baseline.
Unlimited mode. AWS uses an "adjusted balance": (previous balance − previous surplus) + (earned − used). If it's positive, that number becomes the balance and the surplus is zero. If it's negative, the balance is zero and the surplus equals the negative amount. Here's an illustration on a t3.small, which earns 24 an hour, or 2 every five minutes:
- Interval 1: starts with a balance of 3, spends 8. Adjusted = 3 + (2 − 8) = −3. Balance 0, surplus 3.
- Interval 2: nearly idle, spends 1. Adjusted = (0 − 3) + (2 − 1) = −2. Balance 0, surplus 2.
- Interval 3: spends 1. Adjusted = −1. Balance 0, surplus 1.
- Interval 4: spends 1. Adjusted = 0. Both at zero.
- Interval 5: spends 1. Adjusted = +1. Balance 1, surplus 0. The balance finally starts to grow.
Look at intervals 2 through 4. The server was almost idle, yet CPUCreditBalance read zero for fifteen minutes. That's debt being paid, and it's the whole explanation for the "why is my balance still zero?" puzzle. Nothing was broken.
Reading the shapes on your own graph:
- Balance rising to a flat top: the drawer is full and newly earned credits are being discarded. You have headroom, and possibly a bigger instance than you need.
- A staircase down through busy hours and back up overnight: healthy burstable behavior. This is what T instances are designed for.
- Down, and never recovering: the workload has outgrown the size.
- Flat at zero while surplus climbs (Unlimited): the instance is borrowing. Fast, but building a bill.
- Flat at zero while surplus falls (Unlimited): the instance is repaying. Give it time.
- Flat at zero with no surplus metric (Standard): you're in Situation A.
Jake: "Wait, so the exact same flat zero can mean 'fine' or 'you're being throttled'?"
Ethan: "Exactly, and that's why you never read one graph alone. The balance tells you what happened to the drawer. The mode tells you what that means. Read both."
Situation A: Standard mode, balance at zero
This is the textbook case. Your workload spent credits faster than the instance earned them, the drawer emptied, and CPU has been pulled back toward baseline. The symptoms are recognizable: a CPU graph that climbs with traffic and then stops at a hard ceiling far below 100%, a credit balance that's flat at zero, and slow pages that stay slow.
How long does a full drawer last? Here's the arithmetic from AWS's own formulas (credits spent per minute = vCPUs × utilization × 1 minute). It assumes a full balance, Standard mode, and every vCPU flat out at 100%:
| Instance | Spent per hour at 100% | Earned per hour | Net drain per hour | Full balance lasts about |
|---|---|---|---|---|
| t3.nano | 120 | 6 | 114 | 1 hour 15 minutes |
| t3.micro | 120 | 12 | 108 | 2 hours 40 minutes |
| t3.small / t3.medium | 120 | 24 | 96 | 6 hours |
| t3.large | 120 | 36 | 84 | 10 hours |
| t3.xlarge | 240 | 96 | 144 | 16 hours |
| t3.2xlarge | 480 | 192 | 288 | 16 hours |
Treat Table 3 as a rough guide, not a stopwatch. Real workloads swing up and down, and because AWS lowers CPU gradually as the balance runs low, the slowdown starts before zero. But it shows why a t3.small that felt fine through a quiet week can fall over in one afternoon of real traffic.
Now do it with your own numbers. Pipe your seven-day average CPU into this: credits spent per hour = vCPUs × average CPU% × 60. Then subtract the earn rate from Table 1. As an illustration only, suppose Jake's t3.medium averaged 35% over a busy week. That's 2 × 0.35 × 60 = 42 credits spent per hour, against 24 earned. The net drain is 18 credits an hour, and a full 576-credit drawer would last about 32 hours. If the average was 20% (the baseline), the drain is zero and the balance holds steady. Averages hide the swings, but they tell you which side of the line you live on.
Refilling is much slower than draining. The drawer holds 24 hours of earnings, so a t3.medium that started at zero and stayed nearly idle would take about a day to fill its 576 credits. Idle isn't perfectly idle, so plan for a bit longer. If your traffic has a regular rush, whether that's the first of the month when everyone recharges their phones or a Saturday sale, the drawer may never get its rest.
The fix ladder, cheapest to most drastic:
- Find the waste. Look at what's burning CPU with an operating system tool (Task Manager on Windows, or a process viewer on Linux). A runaway job, a backup running at the wrong hour, or a process you don't recognize can drain the drawer for nothing. Fixing it is free.
- Let it recover. If the load was a one-off, do nothing and let the balance rebuild. Free, but slow, and it only works when the cause is gone.
- Switch to Unlimited. This changes the setting on the running instance, with no rebuild. The steps follow this list. It removes the credit ceiling but can add a charge.
- Move up a size in the T3 family. Bigger sizes earn more credits per hour, and t3.xlarge and t3.2xlarge raise the baseline to 40%. Check the EC2 documentation for the resize procedure and plan it for a quiet hour, because resizing is a real change to your server.
- Move to a fixed-performance family such as M. If your average load is high all day, a burstable instance is the wrong shape. The cost section below shows where the crossover sits.
- Split the workload. Put the always-busy part (say, the database) on steady hardware, and leave the idle-most-of-the-time part (an admin page, a nightly job) on the T3.
And here's how to do step 3, which is the one most people want.
- Open the EC2 console and choose Instances in the left navigation pane.
- Select the instance. (You can select several to change them together. The option only enables if you've selected a T instance.)
- Choose Actions, then Instance settings, then Change credit specification.
- Under Unlimited mode, check the box next to the instance ID, and confirm.
- Or use the CLI (swap in your Region and instance ID):
aws ec2 modify-instance-credit-specification \ --region us-east-1 \ --instance-credit-specification "InstanceId=i-1234567890abcdef0,CpuCredits=unlimited" - Look at the Credit specification field again to be sure it now reads
unlimited, and keep an eye onCPUSurplusCreditBalancefrom here on.
AWS says you can switch a running or stopped T instance between the two modes at any time. When you go from Standard to Unlimited, your existing CPUCreditBalance carries over.
⚠️ What Unlimited actually risks
Surplus credits that aren't paid down cost money. AWS charges them when they exceed what the instance can earn in 24 hours (charged at the end of the hour), when you stop or terminate the instance, and when you switch back to Standard. Switching back to Standard charges the whole CPUSurplusCreditBalance immediately. Don't flip modes back and forth as an experiment while a balance is outstanding.
✅ Why step 3 is the one to use first
It's reversible, it takes minutes, and it changes only one setting. It also gives you data: a week of CPUSurplusCreditBalance and CPUSurplusCreditsCharged tells you whether your workload really needs bigger hardware or was just running into a ceiling. Resizing first means paying to find out.
Situation B: Unlimited mode, zero balance, and everyone's confused
You're on the default t3 setup, you saw CPUCreditBalance sitting at zero, and much of the advice you can find treats that as "your throttle." In Unlimited mode it isn't. This is the popular advice that's wrong for your setup.
An Unlimited instance that runs out of accrued credits doesn't slow down. It starts spending surplus credits, and CPUSurplusCreditBalance rises. The instance stays fast. What changes is the bill, and only if the average stays above baseline.
The confusing part comes afterward, and you saw it in the worked example above. Suppose your load drops. The instance is idle again and earning credits, but AWS's documentation says surplus credits are always paid down before the instance accrues earned credits. So the visible balance stays at zero for a while, even though the CPU is bored. This isn't a fault. Once CPUSurplusCreditBalance returns to zero, CPUCreditBalance starts climbing again.
What Unlimited does and doesn't cover:
- It covers CPU credit exhaustion. It doesn't fix a lack of memory, a saturated disk, or a network limit.
- It doesn't remove the cost of sustained load. It converts a slowdown into a charge.
- The credits an instance can spend as surplus without an extra charge equal its 24-hour earning maximum (a t3.micro can spend up to 288 without being charged, for example).
♂️ Jake's Reality Check
"So my server can be 'in debt' and I don't even get a warning? That sounds like a phone plan with hidden roaming charges."
The straight answer. Only if you never look. The debt is visible in CPUSurplusCreditBalance, and the part that costs money is visible in CPUSurplusCreditsCharged. Neither raises an alarm on its own, which is why the alarms section exists. It's a fair complaint that the default gives you no warning.
Ethan: "Think of it as an overdraft with a fixed fee. Overdraft isn't evil. It gets you through a bad week. It becomes a problem when it's how you live."
Why is my t3 in Standard mode when the default is Unlimited?
If the graph says Standard and nobody on your team remembers choosing it, one of these is the likely story. AWS documents each of them.
1. Someone chose it at launch. In the launch wizard, the Credit specification field under Advanced details overrides the account-level default. Whoever launched the instance may have chosen Standard on purpose, or clicked past it.
2. The account default was changed. Each burstable family has a default credit specification that can be set per Region for the whole account. It applies to instances launched from the AWS CLI, and it doesn't touch instances that already exist.
3. A launch template says so. A launch template is a saved recipe for launching instances, and its Credit specification setting decides how its instances start. An Auto Scaling group (the feature that adds and removes instances automatically) launches from one.
4. It's on a Dedicated Host. T3 on a Dedicated Host is Standard only. Unlimited isn't supported there.
5. It's been stopped for more than seven days. On T3, T3a, T4g and T8i, the credit balance persists for seven days after a stop. If you start it inside that window, nothing is lost. After that, the credits are gone, and a Standard-mode instance starts from an empty drawer. Because these families get no launch credits, there's no head start to soften it. Here's a practical trick from the documented rules: AWS lets you change the credit mode on a stopped instance, so if you're about to start something that's been off for weeks and it's in Standard mode, switch it to Unlimited first. Note the flip side, too: stopping an Unlimited instance charges any outstanding surplus, so a stop isn't free of consequences.
6. You're reading a T2 doc. T2 behaves differently: Standard by default, launch credits at each start, and all credits lost on a stop. If your tutorial is for T2, it doesn't describe your t3.
7. Someone switched it on purpose, for cost. AWS allows the switch in either direction at any time, so a teammate can move an instance to Standard. I have no way to see whether that happened. Ask before you assume the setting is a mistake.
The launch template is the first place to look, because a template keeps re-creating the problem every time it launches something new. Fixing one instance and leaving the template alone is bailing water without patching the hole. That's the next section.
Fixing it at the source: launch templates, Auto Scaling groups and the account default
Changing the mode on a running instance fixes today. This section fixes the next launch. AWS specifically recommends Unlimited for Auto Scaling groups: instances that are launched or restarted need CPU credits to start up smoothly, and Unlimited lets them use surplus credits so there are no performance restrictions during startup. AWS also says you must use a launch template to launch instances as Unlimited in an Auto Scaling group, since a launch configuration doesn't support it.
- Create a launch template that sets Unlimited. In the console, follow AWS's "create a launch template using advanced settings" procedure. Under Advanced details, set Credit specification to Unlimited, then choose Create launch template. Or use the CLI:
aws ec2 create-launch-template \ --launch-template-name my-launch-template \ --version-description FirstVersion \ --launch-template-data CreditSpecification={CpuCredits=unlimited} - Attach it to the group. In the EC2 console, choose Auto Scaling Groups, select your group, then Actions, Edit. On the Details tab, pick your launch template for Launch Template and choose Save. Use the same Region you used for the template.
- Set the account default. In the EC2 console Dashboard, find the Account attributes card, and under Settings choose Default credit specification, then Manage. For each instance family, choose Unlimited or Standard, and choose Update. It's per Region, so repeat for every Region you use. You can change a family's default once in a rolling five-minute window and up to four times in 24 hours. From the CLI:
aws ec2 modify-default-credit-specification \ --region us-east-1 \ --instance-family t3 \ --cpu-credits unlimited - Remember the existing instances. A changed default doesn't affect instances that are already running or stopped. Select each affected instance (you can select several at once) and use Change credit specification, as shown earlier.
One caveat about the launch wizard: if someone picks a value in the wizard, it overrides the account default. And if you launch with the CLI without naming a credit specification, you get the account default. So the default protects your automation, but not a person clicking through a form.
Auditing what you have. The command describe-instance-credit-specifications has two quirks worth knowing. Without any instance IDs, it returns only instances set to Unlimited (plus ones that used to be), so it can't list your Standard ones by itself. And if you pass the ID of an instance that isn't a burstable type, it reports standard, so a non-T instance can look like a Standard-mode T instance in a careless script. To audit Standard instances, list your instance IDs first, then pass them in.
✅ The order to work in
Fix the running instance first (it's hurting now), then the launch template and Auto Scaling group, then the account default. In that order, nothing you fix can be undone by the next launch.
Situation C: credits are fine, but the server still crawls
Here's the honest truth about a lot of "t3 slow" stories: the CPU is not the problem. If the CPU graph is low and the credit balance is healthy (or Unlimited, with no surplus building), stop staring at credits. Four other things throttle a small server, and two of them are also "burst" systems with credits of their own. Not the same credits, which is the confusing part.
Memory. A small instance can run out of RAM long before it runs out of CPU credits. AWS's burstable documentation includes a warning on this exact point: the size you choose has to meet the memory needs of your operating system and applications, and a graphical operating system such as Windows might need a t3.micro or larger for many uses. So if you put a Windows desktop on a t3.nano and it feels awful, no credit setting is going to help. Here's the catch for diagnosis: EC2 doesn't publish operating-system-level memory or disk usage to CloudWatch by default. To see it, you install the unified CloudWatch agent, which then sends metrics such as mem_used_percent into a CWAgent namespace. AWS notes that these count as custom metrics, which are billed by storage and API use. Without the agent you'd be diagnosing memory with your eyes closed.
The disk's own burst bucket (gp2). An EBS volume is the virtual hard drive attached to your instance, and its performance is measured in IOPS (input/output operations per second: how many reads and writes it can handle each second). The older gp2 volume type has baseline performance of 3 IOPS per GiB of size, with a floor of 100 IOPS. Volumes under 1 TiB can burst up to 3,000 IOPS using I/O credits, and each volume starts with 5.4 million of them, enough for at least 30 minutes at the maximum burst. When the credits are gone, the volume falls back to its baseline. A 100 GiB gp2 volume has a baseline of just 300 IOPS, and AWS's table shows its full credit bucket lasting about 2,000 seconds at 3,000 IOPS and taking about 18,000 seconds (five hours) to refill from empty. You can watch the bucket with the BurstBalance metric and set an alarm on it. The newer gp3 type doesn't use burst performance: it delivers a consistent 3,000 IOPS and 125 MiB/s baseline, and AWS says you can migrate from gp2 to gp3 with Elastic Volumes operations without interrupting your instance.
The instance's own EBS limit. Separately from the volume, smaller EBS-optimized instances have their own lower baselines and rely on burst credits for peaks. On instance sizes where the baseline is below the maximum, CloudWatch shows EBSIOBalance% and EBSByteBalance%, along with checks named InstanceEBSIOPSExceededCheck and InstanceEBSThroughputExceededCheck that flip to 1 when the instance hits its EBS limit. AWS's Compute Blog points at these for detecting throttling.
Network. AWS's CPU-credit page carries a note that burstable network performance is a separate topic. Instances with 16 vCPUs or fewer are documented with "up to" bandwidth, which means they have a lower baseline and use network I/O credits to burst, typically for 5 to 60 minutes depending on size. Inbound and outbound traffic have separate credit buckets, a stopped instance doesn't earn network credits, and burst is best effort because burst bandwidth is a shared resource. To see the baseline for a type, AWS's documentation shows the describe-instance-types command (their example uses C5, and you can swap in t3):
aws ec2 describe-instance-types \
--filters "Name=instance-type,Values=t3.*" \
--query "InstanceTypes[].[InstanceType, NetworkInfo.NetworkPerformance, NetworkInfo.NetworkCards[0].BaselineBandwidthInGbps]" \
--output table
Status checks. EC2 also publishes StatusCheckFailed, StatusCheckFailed_Instance and StatusCheckFailed_System. If one of those is red, you're not looking at a performance problem but at a broken instance, and the fix path is different.
Jake: "So there are credits for CPU, credits for the disk, credits for the instance's disk connection, and credits for the network? Four buckets?"
Ethan: "Four buckets, four different names, four different graphs. That's the honest answer. And one more, because it trips up beginners: if your AWS account is new, the Free Tier page also uses the word 'credits,' meaning account dollars, not CPU. Same word, unrelated thing. When someone says 'my credits ran out,' ask which credits before you touch anything."
| Bucket | Metric to graph | What "empty" does |
|---|---|---|
| CPU credits | CPUCreditBalance (plus surplus metrics in Unlimited) | Standard: CPU held near baseline. Unlimited: borrows and bills |
| gp2 volume I/O credits | BurstBalance | Volume falls back to its baseline IOPS or throughput |
| Instance EBS burst | EBSIOBalance%, EBSByteBalance% | Instance-to-disk traffic limited to the instance's baseline |
| Network I/O credits | Compare traffic to the type's baseline bandwidth | Returns to baseline bandwidth (separate inbound and outbound buckets) |
♂️ Jake's Reality Check
"Great, now the problem could be in four places. How do I know which bucket to look at first?"
The straight answer. Match the symptom. Slow while the site is thinking (page builds, searches): CPU or memory. Slow while it's reading or writing files (uploads, database, backups): the disk buckets. Slow while it's sending large files to customers: network. It's a starting rule of thumb, not an AWS rule, but it points you at the right graph first.
What it really costs: when a t3 stops being the cheap option
Serious money topic, so I'm keeping the tone flat. The numbers below come from AWS's own worked example in the Unlimited mode documentation. They're based on us-east-1 and Linux, and prices change, so read the live EC2 On-Demand pricing page before you decide anything.
AWS says T instances can save up to 15% over M instances. That saving assumes low average CPU. AWS's documentation works through the crossover for a t3.large: it's $0.0835 an hour against $0.096 for an m5.large, a $0.0125 gap. The documentation's example rate for surplus credits is $0.05 per vCPU-hour, which is about $0.000833 a minute. Divide the $0.0125 gap by that minute rate and you get 15 extra burst minutes per hour per vCPU. On a 2-vCPU instance that's 12.5% more CPU on top of the 30% baseline, so the t3.large costs the same as the m5.large at 42.5% average CPU, and more above it.
| T3 size | Compared with | Breakeven average CPU (24-hour) |
|---|---|---|
| t3.large | m5.large | 42.5% |
| t3.xlarge | m5.xlarge | 52.5% |
| t3.2xlarge | m5.2xlarge | 52.5% |
AWS also gives a blunt rule of thumb: a T3 that bursts continuously at 100% CPU ends up costing about 1.5 times an equivalent M5. In other words, running a permanently busy workload on a t3 in Unlimited mode is the most expensive way to run it.
Here's how to use it. Take a week of your instance's CPUUtilization and read the average. If it sits below your size's baseline, you're in the sweet spot, and slowness came from somewhere else. If it sits between baseline and the breakeven number, Unlimited is a fair deal: you pay a little extra for the busy hours. If it sits above breakeven, you're paying a premium for flexibility you aren't using, and a fixed-performance instance is cheaper and simpler.
Ethan: "A t3 is a good weekday car for a short commute. If you drive it across the country every day, it doesn't get more efficient. It just gets more expensive."
Back to the illustration from earlier: Jake's t3.medium at a 35% weekly average sits above its 20% baseline. In Standard mode that's a server that will run dry. In Unlimited mode it's a server that runs fine and generates a steady line item. Neither is a good long-term home, and that's what these numbers are for. They're not there to scare him, but to tell him which door to walk through.
Set the alarms so this never surprises you again
An alarm is CloudWatch watching a metric for you and sending a message when it crosses a line you chose. AWS's Unlimited documentation recommends exactly this: use CloudWatch metrics to track credit usage and set up alarms so you're told when the instance is spending more than the baseline provides.
For Standard mode: alarm when CPUCreditBalance falls below a threshold. Table 1 gives you the ceiling for your size. As a suggestion of mine, not AWS guidance, start at half the maximum and adjust to your traffic. A t3.medium's ceiling is 576, so something near 288 gives you hours of warning.
For Unlimited mode: alarm when CPUSurplusCreditsCharged goes above zero, since that's the metric that counts surplus credits that incur an extra charge. Optionally add one on CPUSurplusCreditBalance to get an earlier heads-up.
For the disk: alarm on BurstBalance if you use gp2 volumes. AWS's documentation says you can set an alarm that notifies you when it drops to a level you choose. On instance types that publish them, add EBSIOBalance% and EBSByteBalance%.
For memory: install the CloudWatch agent, then alarm on mem_used_percent. Without the agent there's nothing to alarm on.
To pull the numbers from the command line, AWS's documentation shows this pattern for CPU. Swap the metric name to CPUCreditBalance to look at credits. For periods longer than five minutes, AWS says to use the Sum statistic for CPUCreditUsage rather than Average:
aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 \
--metric-name CPUUtilization \
--period 3600 \
--statistics Maximum \
--dimensions Name=InstanceId,Value=i-1234567890abcdef0 \
--start-time 2026-09-13T00:00:00 \
--end-time 2026-09-20T00:00:00
Two edge cases from the CloudWatch documentation are worth knowing. By default EC2 metrics arrive in five-minute points, and detailed monitoring gives one-minute points for the standard metrics, though the credit metrics stay at five minutes. And metrics with no new data in the past two weeks vanish from the console and from list-metrics. If you stopped an instance for a while and its graphs seem to have disappeared, that's why.
Jake: "Five-minute points. So a spike that lasts a minute won't show?"
Ethan: "It shows up averaged into a five-minute point. A short burst uses a small fraction of a credit, so it doesn't drain much. But that's also why a graph can read 55% while individual minutes hit 90%. Don't read one point as gospel."
A ten-minute weekly habit (my suggestion, not an AWS requirement): once a week, open the three credit graphs for each T instance you care about. Look for a staircase that recovers, not one that only goes down. Note the week's average CPU against your size's baseline. If CPUSurplusCreditsCharged was nonzero, write down when. Two weeks of notes will tell you more than any generic guide.
Which fix for which situation: a decision table
| Situation | First move | If that isn't enough |
|---|---|---|
| Standard, balance at zero, busy right now | Switch to Unlimited | Bigger T3, then a fixed-performance family |
| Unlimited, CPUSurplusCreditsCharged above zero most days | Compare average CPU to the breakeven table | Move to a fixed-performance family |
| Unlimited, balance at zero, CPU idle | Wait: surplus is being repaid | Watch CPUSurplusCreditBalance fall to zero |
| Standard instance stopped for weeks | Switch to Unlimited before starting | Fix the launch template |
| Credits healthy, memory tight | Install the CloudWatch agent to see it | Choose a size with more memory |
| gp2 BurstBalance near zero | Migrate the volume to gp3 | Reduce disk writes or provision more performance |
Which instance should you move to?
If the diagnosis says "outgrown the burstable model," here are the options in AWS's own words, as of the documentation at the time of writing:
- T3. Intel Xeon Scalable processors. AWS describes it as the best peak price-performance for x86 workloads.
- T3a. AMD EPYC processors, at about 10% lower cost than T3, per AWS.
- T4g. AWS Graviton2 (Arm-based) processors, with up to 40% better price-performance and 20% lower cost versus T3, per AWS. It's Arm, so your software and machine image must support Arm.
- T8i. Intel Granite Rapids processors, with up to 30% better price-performance than T3, per AWS. At the time of writing, the credit table I read lists T8i sizes from nano to medium.
All four share the same credit system: the same Standard and Unlimited modes, the same seven-day balance persistence, and the same credit earn rates for matching sizes. So switching within the T family changes cost and speed, not the underlying behavior. A workload that outgrew t3 will outgrow t4g as well. AWS lists the supported purchasing options for T instances as On-Demand, Reserved, Dedicated Instances (T3 only), Dedicated Hosts (T3 only, Standard mode only) and Spot.
For sustained load, the fixed-performance M family is the alternative AWS itself uses in its comparison. And before you guess, AWS's best-practice advice is to enable AWS Compute Optimizer and read its recommendations. It looks at your usage and can suggest sizing up, sizing down or another family. One detail matters here: Compute Optimizer only analyzes memory if the CloudWatch agent is installed, so install it if you want recommendations that account for RAM.
If you're on the AWS Free Tier: AWS's documentation says accounts created on or after July 15, 2025 can use t3.micro, t3.small, t4g.micro, t4g.small, t8i.micro and t8i.small for six months or until account credits run out. Earlier accounts under 12 months old can use t2.micro (or t3.micro where t2.micro isn't available). A free-tier t3.micro has the same 12 credits per hour and 10% baseline as any other t3.micro, so a sustained job will still exhaust it.
Ethan: "My opinion, since you'll ask: if a small business server is busy most of the day, skip the debate and start with the fixed-performance family. You'll never wonder about credits again. Keep T for the things that really are idle most of the time."
Five things people say about t3 credits (four are wrong, one is half right)
1. "Zero credits means your instance is throttled." Wrong for Unlimited, which is the default. Zero accrued credits with a positive surplus balance is a healthy borrowing state. It's only a throttle in Standard mode.
2. "Reboot it and the credits come back." Wrong. Nothing in AWS's documentation says a restart refills the balance. What the documentation does say: credits on a running instance don't expire, and on T3-family instances the balance persists for seven days after a stop. Restarting doesn't manufacture credits. The only thing that fills the drawer is time spent below baseline.
3. "A CloudWatch reading of 60% on a 2-vCPU instance is fine, because 30% × 2." Wrong. AWS's table note says the baseline percentage is per vCPU and that a t3.large running exactly at baseline shows as 30% in CloudWatch. Compare CloudWatch's number to the baseline column directly.
4. "Unlimited mode is free." Wrong. It's free only while your 24-hour average stays at or below baseline. Above that, you pay a flat rate per vCPU-hour for the excess.
5. "Just pick a bigger instance." Half right. A bigger T3 earns more credits (a t3.large earns 36 an hour versus 24 on a t3.medium) and t3.xlarge raises the baseline to 40%. But if your average is above the breakeven point, a bigger t3 is still the more expensive way to run a steady load, and it won't fix a memory or disk problem at all.
Jake: "So half the internet's advice on this is one setting and a prayer?"
Ethan: "A lot of it was written when T2 was the default, and T2 really did work that way. The advice didn't change when the defaults did."
When nothing on this list fixes it
Some things I can't do from here, and you should know where those limits are. I can't see your account, your graphs, or your application. If your credits are healthy, your memory has headroom, your disks aren't throttled and your network isn't capped, and the server is still slow, the cause is probably inside the application: a slow database query, an external service that's timing out, or code that got heavier with a recent release. AWS's metrics can't tell you that. The credit system can only explain credit problems.
Here's what to gather before you ask anyone for help, because a good question gets a good answer:
- The instance type and its credit specification (standard or unlimited).
- A graph, over at least three days, of
CPUUtilization,CPUCreditBalance,CPUCreditUsage, plus the two surplus metrics if you're on Unlimited. - Memory and disk usage from the CloudWatch agent, if installed.
- Your volume type, and
BurstBalanceif it's gp2. - The exact time the slowness started, and anything that changed just before: a deploy, a new customer, a bigger import.
Post those on AWS re:Post or bring them to AWS Support if your plan includes it. If the graphs show a status check failing, treat it as an instance problem and follow the status-check path in the EC2 troubleshooting documentation, not this one.
One more admission. Every number in this post is from AWS's published documentation as it stood in September 2026, and nobody here has run these steps against your account. Names of console pages and buttons do get rearranged. If a label doesn't match, the CLI commands are the more stable route, and the AWS CLI reference will show the current syntax.
Frequently asked questions about slow t3 instances and CPU credits
Why is my t3 instance suddenly slow?
The most credit-related cause is a Standard-mode instance that ran out of CPU credits, so AWS lowered its CPU toward the baseline. Check the credit specification and CPUCreditBalance first. If the instance is in Unlimited mode, credits aren't slowing it down, and you should look at memory, disk burst limits (such as gp2 BurstBalance), the instance's EBS limits, network burst limits and the application itself.
How do I check my t3 instance's CPU credit balance?
In the CloudWatch console, choose Metrics, then EC2, then Per-Instance Metrics, and search for your instance ID to graph CPUCreditBalance. You can also see the credit specification in the EC2 console on the instance's Details tab. These credit metrics update every five minutes. In Unlimited mode, add CPUSurplusCreditBalance and CPUSurplusCreditsCharged.
What is the baseline CPU utilization of a t3 instance?
It depends on size: 5% for t3.nano, 10% for t3.micro, 20% for t3.small and t3.medium, 30% for t3.large, and 40% for t3.xlarge and t3.2xlarge. The formula is (credits earned per hour ÷ number of vCPUs) ÷ 60. AWS's note says a t3.large at baseline reads 30% in CloudWatch, so compare the CloudWatch percentage directly to these numbers.
Is a t3 instance in Unlimited mode throttled when CPU credits reach zero?
No. In Unlimited mode the instance spends surplus credits to keep bursting and pays them down later from earned credits. It isn't held to baseline. What can happen is a charge: if the average CPU over a 24-hour period exceeds the baseline, AWS bills the excess at a flat rate per vCPU-hour.
Why is my CPUCreditBalance zero in Unlimited mode even when the server is idle?
Because AWS pays down surplus credits before the balance starts to grow. If the instance borrowed credits earlier, the credits it earns now go to that debt first, so CPUCreditBalance stays at zero until CPUSurplusCreditBalance returns to zero. This is normal behavior, not a fault, and the worked example earlier in this post walks through the arithmetic.
How do I switch a t3 instance from Standard to Unlimited?
In the EC2 console, select the instance, choose Actions, then Instance settings, then Change credit specification, and check the Unlimited mode box. From the CLI, run aws ec2 modify-instance-credit-specification with CpuCredits=unlimited. AWS says you can switch a running or stopped instance at any time, and your accrued credit balance carries over.
Does switching to Unlimited mode cost extra?
Only if surplus credits aren't paid down. There's no extra charge while your average CPU over a 24-hour window stays at or below baseline. Above that, you pay a flat additional rate per vCPU-hour. Surplus credits are also charged when they exceed the 24-hour earning maximum, when you stop or terminate the instance, and when you switch back to Standard. Check the EC2 On-Demand pricing page for the current rate.
Do CPU credits reset when I stop and start or reboot a t3 instance?
No refill happens. Credits on a running instance don't expire, and on T3-family instances the balance persists for seven days after a stop. If you start the instance within seven days nothing is lost, and after seven days the credits are gone. AWS documents no mechanism where a restart tops up the balance.
How long does a t3 instance take to earn its CPU credits back?
The balance can hold at most 24 hours of earnings, so refilling an empty balance from a nearly idle instance takes about a day. A t3.medium, for example, earns 24 credits an hour and holds up to 576. The instance only accrues credits while its CPU use is below baseline, and in Unlimited mode surplus credits are repaid first, so busy instances refill more slowly.
Why did my new t3 instance launch in Standard mode?
T3 launches as Unlimited by default, so something chose Standard. Common sources are the Credit specification field in the launch wizard, a launch template, the account-level default credit specification for that Region, or a Dedicated Host, where T3 runs as Standard only. Fix the running instance, then the template, then the account default.
Does a t3 instance get launch credits?
No. Launch credits apply only to T2 instances in Standard mode. T3, T3a, T4g and T8i don't earn them because they launch as Unlimited by default and can burst immediately. A T3 running in Standard mode has to earn its credits like any other instance.
Should I upgrade to a bigger t3 size or switch to an M-family instance?
Look at your average CPU. If it is at or below your size's baseline, a bigger size is rarely needed and the slowness is elsewhere. If it is between baseline and breakeven, Unlimited or a bigger T3 is a fair choice. AWS's example puts breakeven for t3.large against m5.large at 42.5%, and above that a fixed-performance instance costs less.
Is t3, t3a, t4g or t8i better for burstable workloads?
They share the same credit system, so the choice is about price, processor and compatibility. Per AWS, T3a costs about 10% less than T3, T4g offers up to 40% better price-performance on Arm processors, and T8i offers up to 30% better price-performance than T3 on newer Intel processors. None of them fixes a workload that stays busy all day.
Can slow performance on a t3 instance be caused by something other than CPU credits?
Yes. Memory shortages, an empty gp2 burst bucket (BurstBalance), the instance's own EBS limits (EBSIOBalance% and EBSByteBalance%), network burst limits, failing status checks and slow application code can all cause it. EC2 doesn't report operating-system memory by default, so install the CloudWatch agent to see it.
What CloudWatch alarms should I set for a t3 instance?
For Standard mode, alarm on CPUCreditBalance falling below a threshold (half the maximum is a starting point of mine, not an AWS rule). For Unlimited, alarm on CPUSurplusCreditsCharged going above zero. Add BurstBalance for gp2 volumes, and mem_used_percent if you've installed the CloudWatch agent.
Do T3 instances on a Dedicated Host support Unlimited mode?
No. AWS documents that T3 instances on a Dedicated Host launch as Standard and Unlimited mode isn't supported there. On a Dedicated Host, a T3 that exhausts its credits is lowered to baseline like any Standard instance, so watch the credit balance closely or use a fixed-performance family.
Back to Jake's Saturday. Here's how his story ends, as an illustration and not a case study: Ethan walked him through the same order you just read. Mode first, then balance, then the fix that costs the least and can be undone. The lesson wasn't the setting itself. It was that a flat zero on a graph is a clue and never a verdict, and that a customer-facing page deserves an alarm more than it deserves a bigger server.
Revision note. Written September 2026. Console labels, credit-table sizes, surplus-credit rates and default credit settings can change, so this post will need updating if AWS revises them or adds new burstable families. If you're reading this while a slow server is costing you customers, you're not careless for not knowing this system existed, because it's genuinely confusing, and you'll get through it.
π RECOMMENDED AWS TROUBLESHOOTING & GUIDES