How to Improve AWS Performance Without Spending More Money: Complete Step by Step Guide
By Braincuber Team
Published on March 31, 2026
Identifying performance issues has always been the holy grail of engineering. You want to be known as the software engineer who's able to diagnose and rectify the performance issue that came up in production. This complete tutorial walks through a real-world case study of diagnosing AWS performance problems — from CPU throttling and IOPS limits to query optimization — and shows you how to fix them without simply throwing money at the problem. The techniques covered here apply to any AWS deployment experiencing unexpected slowdowns under load.
What You'll Learn:
- How AWS burst credits work and why your EC2 instance might be throttled
- Understanding RDS IOPS limits and how storage allocation affects performance
- How RAM impacts database IOPS through the InnoDB buffer pool
- Using EXPLAIN ANALYZE to identify slow queries and full table scans
- How the BINARY function can destroy query performance by bypassing indexes
- Column collation strategies for maintaining index effectiveness
- Practical steps to diagnose and fix performance issues without upgrading instances
Step 1: Identifying the Performance Problem
The problems typically start when you run a load test to understand whether a specific API endpoint can handle expected traffic. You point your load testing tool at the server and promptly see a significant percentage of requests fail with average response times far exceeding expectations.
Run Load Tests
Use tools like JMeter to simulate expected traffic. Launch threads in a loop to understand throughput capacity and failure rates under load.
Compare Local vs AWS Performance
Run the same load test locally. If local performance exceeds AWS, the issue is likely infrastructure-related rather than application logic.
Check CPU Utilization
Monitor CPU usage during load tests. If CPU never exceeds 10% but requests are slow, you may be experiencing throttling rather than capacity issues.
The Throttling Trap
When CPU utilization stays below 10% but requests are slow, don't assume the application is efficient. On t2/t3 instances, this often means your CPU is being throttled at the baseline level because burst credits have been exhausted.
Step 2: Understanding AWS CPU Throttling and Burst Credits
AWS uses virtual CPUs (vCPUs) to describe computing power. For t2 class instances, AWS manages CPU allocation through something called Burst Credits. Understanding this mechanism is crucial for diagnosing performance issues.
AWS provides a baseline CPU utilization beyond which you pay for the CPU time you consume. For a t2.micro instance, the baseline is set at 10%. The instance constantly earns credits based on the number of vCPUs it has.
| Calculation Type | Formula | Result |
|---|---|---|
| Earning Credits | 1 vCPU x 10% baseline x 60 minutes | 6 credits per hour |
| Spending Credits (at 15%) | 1 vCPU x 15% CPU x 60 minutes | 9 credits per hour |
| Net Loss (at 15%) | 9 spent - 6 earned | -3 credits per hour |
| Maximum Credits (t2.micro) | Total credit pool | 144 credits |
If you're constantly running at 15% CPU, your instance is losing 3 credits per hour. Once the 144 credit pool runs out, your CPU usage will be throttled at 10% — the baseline utilization. You can confirm CPU throttling by logging into your EC2 instance and running the top command to check the steal time. During load testing, watch as steal time increases to prevent your process from taking additional CPU time.
# SSH into your EC2 instance and run:
top
# Look for the %st (steal time) column
# High steal time indicates CPU throttling
Step 3: Diagnosing RDS IOPS Issues
Even if your EC2 instances aren't being throttled, you might still face performance issues due to RDS IOPS limitations. AWS limits IOPS at the rate of 3 x (storage assigned to your EBS volume). For GP2 storage starting at 20GB, you get 60 IOPS, though AWS provides a minimum of 100 IOPS.
Monitor IOPS Throughout the Day
Check average IOPS at different intervals. A 1-minute interval may show spikes, while a 1-hour interval reveals true averages that can be significantly higher.
Increase EBS Storage Capacity
Increasing storage from 20GB to 100GB raises baseline IOPS from 100 to 300. This is often the simplest and cheapest way to improve database performance.
Enable Performance Insights
Use Performance Insights to identify which queries consume the most IOPS. Note: requires at least db.t3.medium instance class.
| Storage Size | Baseline IOPS (GP2) | Notes |
|---|---|---|
| 20 GB | 100 IOPS (minimum) | Default starting point |
| 34 GB | 102 IOPS | 3 x storage = IOPS |
| 100 GB | 300 IOPS | Significant improvement |
| 200 GB | 600 IOPS | For high-traffic databases |
| 1000 GB | 3000 IOPS | Maximum GP2 baseline |
AWS Limitation: Cannot Downgrade Storage
AWS does not allow downgrading EBS volumes. Once you increase from 20GB to 100GB, you cannot go back. Plan your storage increases carefully and monitor actual usage patterns before committing to larger volumes.
Step 4: Understanding How RAM Impacts Database IOPS
One of the most overlooked factors in database performance is how RAM affects IOPS. AWS measures IOPS as reads and writes to the hard disk itself — not reads/writes to the buffer pool maintained by the InnoDB engine in MySQL.
Small Buffer Pool (1GB RAM)
With 1GB RAM, buffer pool is ~250MB. Loading a 210MB table fills the pool, evicting other data. Constant disk fetches lead to high IOPS.
Large Buffer Pool (4GB RAM)
With 4GB RAM, buffer pool is ~2GB. The 210MB table fits comfortably with room for other data. Dramatically reduces disk IOPS.
When a query loads a large table into the buffer pool, if the pool is too small, it constantly removes other data. This forces the database to go back to disk to fetch that data, leading to more IOPS. Upgrading from db.t2.micro (1GB RAM) to db.t3.medium (4GB RAM) can reduce IOPS from hundreds to single digits — not because the query changed, but because more data fits in memory.
The RAM-IOPS Relationship
If your IOPS suddenly drops to near zero after upgrading RAM, don't panic — this is expected behavior. More data is being served from the buffer pool rather than disk. The query hasn't changed; the data access pattern has improved dramatically.
Step 5: Identifying and Fixing the Offending Query
Even with more RAM, you need to fix the underlying query issue. The table will only grow in size, and constantly increasing RAM isn't a sustainable fix. Use EXPLAIN ANALYZE to understand what's happening.
SELECT oc.oc_number AS ocNumber,
roll.po_number AS poNumber,
item.item_code AS itemCode,
roll.roll_length AS rollLength,
roll.roll_utilized AS rollUtilized
FROM fabric_barcode_rolls AS roll
INNER JOIN fabric_barcode_oc AS oc
ON oc.oc_unique_id = roll.oc_unique_id
INNER JOIN fabric_barcode_items AS item
ON item.item_unique_id = roll.item_unique_id_fk
WHERE BINARY roll.roll_number = 'dZkzHJ_je8'
Running EXPLAIN ANALYZE on this query reveals a full table scan on the roll table, looking at 582,000 rows each time. The BINARY function call is the culprit — it casts each value in the roll_number column to binary, which prevents MySQL from using indexes unless that specific collation is defined on the column in the DDL.
-> Nested loop inner join
(cost=468792.05 rows=582836)
(actual time=0.092..288.104 rows=1 loops=1)
-> Table scan on roll
(cost=60806.85 rows=582836)
(actual time=0.048..230.675 rows=600367 loops=1)
-- Simply remove the BINARY function
WHERE roll.roll_number = 'dZkzHJ_je8'
-- Result: Rows fetched before execution
-- (cost=0.00 rows=1)
-- (actual time=0.000..0.000 rows=1 loops=1)
The BINARY Function Trap
The BINARY function forces MySQL to cast each value in the column to binary for comparison. Since the index isn't built with binary collation, MySQL can't use it and falls back to a full table scan. Removing BINARY or changing the column collation to be case-sensitive fixes the issue permanently.
For a permanent fix that maintains case sensitivity, change the column collation to use the Latin character set and be case-sensitive. This ensures the index is built with case sensitivity, preventing barcode collisions while maintaining index effectiveness.
Step 6: Understanding AWS Challenges and Limitations
AWS has done a wonderful job of abstracting away hardware from millions of software engineers. But it has simultaneously made pricing and resource management difficult to understand. Here are key challenges to be aware of:
Cannot Downgrade EBS Volumes
Once you increase EBS storage, AWS won't allow downgrading. You're stuck with the extra storage and its associated costs even if you don't need it.
Performance Insights Requirements
Performance Insights requires at least db.t3.medium. You can't downgrade to db.t3.micro without losing this critical diagnostic tool.
Documentation Gaps
Poor documentation around burst credits, IOPS limits, and instance capabilities makes it easy to encounter unexpected performance issues.
Consider Aurora DB
AWS Aurora is a managed database that prevents many of these IOPS and throttling issues. It's more expensive but eliminates much of the manual tuning required.
Monitor Before Scaling
Always check query performance and indexing before upgrading instances. A single poorly optimized query can consume more resources than an undersized instance.
Step 7: Complete Performance Optimization Checklist
Follow this systematic checklist to diagnose and fix AWS performance issues without unnecessary spending:
Check EC2 Burst Credits
Run top command and check steal time. If high, your instance is CPU throttled. Consider upgrading to t3 instances or monitor credit balance.
Monitor RDS IOPS at Multiple Intervals
Check 1-minute and 1-hour averages. If consistently above baseline, increase EBS storage to raise IOPS limits (3 x storage GB = IOPS).
Enable Performance Insights
Identify which queries consume the most IOPS. Requires db.t3.medium or larger. Worth the upgrade for diagnostic capabilities.
Run EXPLAIN ANALYZE on Slow Queries
Look for full table scans, nested loop joins on large tables, and missing index usage. These are the primary causes of high IOPS.
Remove BINARY and Function Calls in WHERE Clauses
Functions like BINARY, UPPER(), LOWER() prevent index usage. Change column collation instead for case-sensitive comparisons.
Verify Index Coverage
Check that all columns used in WHERE, JOIN, and ORDER BY clauses have appropriate indexes. Verify index accuracy and consider composite indexes.
Consider RAM vs IOPS Trade-offs
More RAM = larger buffer pool = fewer disk reads. Upgrading RAM can be more cost-effective than increasing IOPS for read-heavy workloads.
Understanding Hardware Is Essential
AWS abstracts hardware away, but understanding how CPU credits, IOPS limits, buffer pools, and indexes work is essential for performance optimization. The abstraction removes the need to manage hardware, but you still need to understand how your application uses it.
Frequently Asked Questions
What are AWS burst credits and how do they affect performance?
Burst credits are CPU credits that t2/t3 instances earn at a baseline rate (10% for t2.micro). When you exceed the baseline, you spend credits. Once credits run out, CPU is throttled to the baseline level, causing significant performance degradation.
How do I calculate IOPS for my RDS instance?
For GP2 storage, IOPS = 3 x storage in GB, with a minimum of 100 IOPS. A 20GB volume gives 100 IOPS (minimum), 100GB gives 300 IOPS, and 1000GB gives 3000 IOPS (maximum baseline for GP2).
Why does the BINARY function cause full table scans?
BINARY casts each column value to binary for comparison. Unless the column's collation is defined as binary in the DDL, MySQL cannot use the index and falls back to scanning every row. Remove BINARY or change column collation to fix this.
How does RAM affect database IOPS?
More RAM means a larger InnoDB buffer pool. When frequently accessed data fits in the buffer pool, MySQL serves reads from memory instead of disk, dramatically reducing IOPS. AWS measures IOPS as disk reads/writes, not buffer pool operations.
Can I downgrade AWS resources after upgrading?
AWS does not allow downgrading EBS volumes — once increased, storage cannot be reduced. You also cannot downgrade RDS instances below db.t3.medium without losing Performance Insights. Plan upgrades carefully and monitor actual usage before committing.
Need Help Optimizing Your AWS Infrastructure?
Our experts can help you diagnose performance issues, optimize database queries, and right-size your AWS resources for maximum performance without unnecessary spending.
