[AWS Cost] A Guide to Cutting AWS Infrastructure Costs by 55% (Graviton Migration & Fixed-Cost Optimization Strategy)
From 2024 through the first half of 2026, while directly designing and building the infrastructure within my division and team, what I focused on most was 'drawing a robust architecture while minimizing unnecessary cloud spending.'
In particular, in this post I want to share in detail the actual quote data and know-how with which I lowered operating costs by up to 55% (about ₩2M/month) versus before — by strategically leveraging the AWS Graviton (ARM) architecture and converting managed services like ALB, NAT Gateway, and RDS into self-built ones. I hope it serves as a practical guide for engineers thinking about infrastructure efficiency.
1. 2026 AWS EC2 instance unit-price comparison (Seoul region) - updated version
The table below is an on-demand pricing table based on the Asia Pacific (Seoul) region, Ubuntu 24.04 LTS (HVM). You can confirm how big a cost difference (about 20%) arises from the single choice of CPU architecture.
| Instance type | vCPUs | CPU architecture | Mem | Storage | Network performance | EC2 (per hour) | per month (30d) | per year (12M) |
|---|---|---|---|---|---|---|---|---|
| m6g.large | 2vCPU | Arm | 8 GiB | EBS Only | Up to 10 Gigabit | $0.094 | $67.68 | $812.16 |
| t4g.xlarge | 4vCPU | Arm | 16 GiB | EBS Only | Up to 5 Gigabit | $0.1664 | $119.81 | $1,437.70 |
| t4g.medium | 2vCPU | Arm | 4 GiB | EBS Only | Up to 5 Gigabit | $0.0416 | $29.95 | $359.42 |
| t2.micro | 1vCPU | x86 | 1 GiB | EBS Only | Low to Moderate | $0.0144 | $10.37 | $124.42 |
| r6g.large | 2vCPU | Arm | 16 GiB | EBS Only | Up to 10 Gigabit | $0.1220 | $87.84 | $1,054.08 |
| r6g.xlarge | 4vCPU | Arm | 32 GiB | EBS Only | Up to 10 Gigabit | $0.2440 | $175.68 | $2,108.16 |
| r5a.xlarge | 4vCPU | x86 | 32 GiB | EBS Only | Up to 10 Gigabit | $0.2720 | $195.84 | $2,350.08 |
| r6gd.xlarge | 4vCPU | Arm | 32 GiB | 1 x 237 NVMe SSD | Up to 10 Gigabit | $0.2768 | $199.30 | $2,391.55 |
| r5.xlarge | 4vCPU | x86 | 32 GiB | EBS Only | Up to 10 Gigabit | $0.3040 | $218.88 | $2,626.56 |
| r6g.xlarge | 4vCPU | Arm | 32 GiB | EBS Only | Up to 10 Gigabit | $0.2440 | $175.68 | $2,108.16 |
| r6g.2xlarge | 8vCPU | Arm | 64 GiB | EBS Only | Up to 10 Gigabit | $0.4880 | $351.36 | $4,216.32 |
Just switching the architecture saves $43.2 a month.
Analyzing the unit-price table above closely, you can confirm that even though the CPU, Memory, Storage, and Network specs are completely identical, about a 20% price difference arises depending on the architecture choice.
| Item | r5.xlarge (x86 architecture) | r6g.xlarge (Arm architecture) | Difference (Savings) |
|---|---|---|---|
| vCPU / Mem | 4 vCPU / 32 GiB | 4 vCPU / 32 GiB | Same |
| Storage / Network | EBS / Up to 10Gbps | EBS / Up to 10Gbps | Same |
| Monthly operating cost (30 days) | $218.88 | $175.68 | -$43.2 (about 20% saved) |
Figure 1. How ARM instance selection is restricted when the architecture (x86) is set
For reference, even if you look at the on-demand instance pricing table, the CPU architecture isn't shown. That table can be checked when you actually create an instance. For example, if you set the architecture to 64-bit (x86) and try to pick the r6gd.xlarge instance type, you'll see it become disabled.
2. Instance-family selection strategy by purpose
Along with cutting costs, you have to use the instance-type family appropriately.
- t family (burstable): optimal for small workloads. It uses CPU credits to cheaply handle intermittent traffic spikes.
- m family (general purpose): choose it when you need a balance of CPU, memory, and network performance. It provides fixed performance and is suitable for stable WAS operation.
- r family (memory optimized): essential for memory-intensive work such as DB, cache (Redis), and large-scale data analysis. In particular, the ARM-based r6g boasts overwhelming cost-efficiency versus x86.
3. Defending fixed costs by self-building instead of managed services (SaaS)
If your infrastructure capability backs it up, you can drastically reduce fixed costs by replacing managed services with self-built ones.
3.1 Using an Nginx Reverse Proxy instead of ALB: saves $16.43/month
ALB is convenient, but fixed costs arise even with no traffic. I completely removed the ALB cost by installing Nginx on the Bastion server, applying Certbot (SSL), and configuring routing directly.
3.2 Building a NAT Instance instead of NAT Gateway: saves $33.75/month
The NAT Gateway that helps the Private Subnet's external communication has expensive hourly charges. If you configure and run the Bastion server as a NAT Instance, you can save about $33.75/month including data-processing costs. (assuming about 30GB of data processed per month)
- NAT gateway charge (USD/hour): USD 0.045
- Charge per GB of processed data (USD): USD 0.045
Note: for a detailed NAT-instance build guide, refer to my previous posts (Part 1 / Part 2).
Building a NAT Instance via an AMI (Part 1)
Building the instance by directly manipulating Linux IP Tables (Part 2): the setup is in Part 1, so refer to Part 2 after the Part 1 setup
3.3 Route53 Domain cost: about $14.51 on a .com basis
Route53: domain fixed costs are hard to reduce, so you can efficiently choose to cut fixed costs from EC2 — which takes the largest share — or from ALB, NAT Gateway, etc. Or you can go to a cheaper domain site and buy it there.
4. RDS risk management and self-installed DB strategy
Oracle RDS (db.m5.4xlarge, etc.) incurs enormous costs reaching $2,800–$6,000/month when licensing is included. Even for a company that already holds the license (BYOL), the RDS operating cost is by no means trivial — it comes to about $1,551.67. To optimize this, I chose the following strategy.
- RDS management fee vs. self-built EC2: if your company already has stockpiled licenses, the cost you pay to RDS is purely a 'management agency fee.' But this cost is large enough to exceed the instance cost.
- The trap of Oracle RDS (BYOL): based on an 8vCPU, 32GiB RAM spec, even if you bring your own (BYOL) Standard Edition Two (SE2) license, the RDS management cost alone paid to AWS reaches about $1,551.67.
- Switching to an ARM-based DB-EC2: to save this cost, instead of RDS I chose an EC2 with an 8vCPU ARM, 64GiB RAM, 512GB Storage spec.
- Monthly operating cost: $382.35 (including EBS storage)
- Result: I immediately saved more than about 75% versus the RDS management fee. I even secured 64GiB — twice the memory of RDS (32GiB) — gaining a performance benefit too.
5. Final cost comparison: managed services vs. self-built (Monthly)
| Item | Qty | USD / Month | Self-built optimized | Managed-service centric | Note |
|---|---|---|---|---|---|
| VPC (EIP) | 1 | 21.9 | ✔ | ✔ | common fixed cost |
| Route53 (Domain) | 1 | 14.53 | ✔ | ✔ | common fixed cost |
| EC2 (Service) ARM | 5 | 175.68 | ✔ | - | 4v CPU ARM 32GiB |
| EC2 (Service) x86 | 5 | 218.88 | - | ✔ | 4v CPU ARM 32GiB |
| EC2 (Bastion) | 1 | 66.4 | ✔ | ✔ | in managed, used only as Bastion (no NAT, Proxy role) |
| EC2 (DB) | 1 | 382.35 | ✔ | - | |
| RDS (BYOL) Oracle | 1 | 1,551.67 | - | ✔ | |
| NAT Gateway | 1 | 33.75 | - | ✔ | in self-built, replaced by NAT Instance |
| ALB | 1 | 16.43 | - | ✔ | in self-built, replaced by Nginx Proxy |
| Total (USD / Month) | 1,263.58 | 2,799.08 | Difference = 1,535.5, up to about 55% saved |
Conclusion: choosing efficient cost reduction
It doesn't mean abandoning all managed services. But if you selectively cut costs using an engineer's capability (ARM migration, self-building NAT/Proxy, self-installing the DB), you can run a much higher-performance architecture within a limited budget.
The fixed-cost saving of about $1,535/month (about ₩2M KRW) is meaningful enough, and I think this too is an important factor to consider from an engineering standpoint.
6. Caveats when migrating to the ARM architecture: compatibility issues and a case
Cutting costs is important, but you must absolutely avoid the risk of a service outage due to an architecture migration. Until just a few years ago, the ARM architecture was often avoided due to compatibility issues, but as of 2026 most major libraries and OSes have been stabilized or are in progress.
I want to share one problem I encountered in a production environment.
The 'DPI-1047' error when integrating Python with Oracle DB
The most common problem when migrating a Python-based service to an ARM instance is driver compatibility.
- The problem situation: if you use the cx_Oracle library — used in the existing x86 environment — as-is on an ARM environment, the DPI-1047 error occurs and DB connection fails. This is because that library has a specific C library dependency.
- The fix: you have to use python-oracledb Thin mode, which needs no Oracle Instant Client install. Thin mode works in pure Python with no C library dependency, so it works perfectly on the ARM architecture too.
If you're currently running a Python service and using cx_Oracle, reduce your trial and error through the detailed fix-guide post below.
References (AWS official)
- AWS On-Demand Instance Pricing
- AWS VPC Pricing
Amazon VPC PricingPublic IPv4 address and VPC-related pricing.aws.amazon.com
📦 Migrated from the Tistory blog I used to run. Original: taehyuklee.tistory.com/33
![[AWS Infra] Building & Configuring a NAT Instance from an AMI to Cut NAT Gateway Costs (Part 1)](assets/posts/nat-instance-build-1/cover.webp)
![[AWS Infra] Building & Configuring a NAT Instance to Cut NAT Gateway Costs (Part 2)](assets/posts/nat-instance-build-2/cover.webp)
![[SQLAlchemy] Fixing the DPI-1047 Python Oracle DB Connection Error on AWS Graviton (ARM) | SQLAlchemy, oracledb](assets/posts/python-oracledb-arm-dpi-1047/cover.webp)
Comments