Show HN: PostgreSQL performance and cost across 23 EC2 instance types
Analysis: PostgreSQL Performance & Cost Across 23 AWS EC2 Instance Types
Source: The Sane Engineer Objective: Provide a data-driven framework for sizing PostgreSQL servers on AWS by balancing data volume, required throughput, and budget.
Stop guessing your instance sizes. Instead, use benchmarked data to find the intersection of performance and price.
🛠️ Benchmark Methodology
The tests were designed to simulate a realistic production environment with the following parameters:
- Database Engine:
PostgreSQL 17 - AWS Region:
us-east-1 - Pricing Model: On-demand
- Concurrency: 32 simultaneous connections
- Workload Distribution:
The Selection Process
To choose the right instance, follow this logic flow:
- Define your Dataset Size.
- Define your Target Throughput (Requests Per Second).
- Identify all instances that exceed that throughput.
- Select the one with the lowest monthly cost.
📉 Case Study: 1 GB Dataset
For a small dataset of 1 GB with a target of 33,000 RPS, the results are as follows:
Recommendation Summary
| Goal | Recommended Instance | Disk | Arch | Cost/Mo | Performance |
|---|---|---|---|---|---|
| Cheapest | m8g.large | gp3-baseline | Graviton | $82 | 45,515 RPS (1.4 target) |
| Safe Pick | m8g.large | gp3-baseline | Graviton | $82 | headroom |
| Max Efficiency | c8i.large | gp3-baseline | x86-64 | ~$84 | 52,203 RPS (Best RPS/$) |
Requirement Checklist:
- Clear 33,000 RPS
- Minimize monthly spend
- Maintain stability (headroom)
Note: 30 out of 52 tested configurations successfully cleared the 33,000 RPS threshold for a 1 GB dataset.
Figure 1: The dashed line represents the cost/performance frontier. Green points denote arm64 (Graviton) and slate points denote x86-64.
📊 Comprehensive Benchmark Results (1 GB)
The following table details the performance of various instance disk combinations.
| Instance Family | Arch | Disk | vCPU | RAM (GiB) | RPS | RPS/$ | $/hr | $/mo | Avg ms | p95 ms | p99 ms | RPS/vCPU | RPS/GiB | Headroom |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
c8i.large | x86-64 | gp3-baseline | 2 | 4 | 52,203 | 451,476 | $0.1156 | ~$84 | 0.61 | 2.16 | 2.79 | 26,102 | 13,051 | 1.6 |
m8g.large | arm64 | gp3-baseline | 2 | 8 | 45,515 | 407,555 | $0.1117 | ~$82 | 0.70 | 2.02 | 2.76 | 22,757 | 5,689 | 1.4 |
m8g.xlarge | arm64 | gp3-baseline | 4 | 16 | 70,871 | 351,826 | $0.2014 | ~$147 | 0.45 | 1.83 | 2.32 | 17,718 | 4,429 | 2.1 |
m7i.large | x86-64 | gp3-baseline | 2 | 8 | 41,305 | 336,586 | $0.1227 | ~$90 | 0.77 | 2.33 | 3.11 | 20,653 | 5,163 | 1.3 |
m7g.xlarge | arm64 | gp3-baseline | 4 | 16 | 58,726 | 317,234 | $0.1851 | ~$135 | 0.54 | 1.98 | 2.44 | 14,681 | 3,670 | 1.8 |
c8i.xlarge | x86-64 | gp3-baseline | 4 | 8 | 64,585 | 308,522 | $0.2093 | ~$153 | 0.50 | 1.85 | 2.27 | 16,146 | 8,073 | 2.0 |
r8g.large | arm64 | gp3-baseline | 2 | 16 | 38,531 | 304,746 | $0.1264 | ~$92 | 0.83 | 2.35 | 3.06 | 19,266 | 2,408 | 1.2 |
m7i.xlarge | x86-64 | gp3-baseline | 4 | 16 | 65,582 | 293,410 | $0.2235 | ~$163 | 0.49 | 1.86 | 2.30 | 16,396 | 4,099 | 2.0 |
r8g.xlarge | arm64 | gp3-baseline | 4 | 32 | 64,627 | 279,821 | $0.2310 | ~$169 | 0.49 | 1.89 | 2.32 | 16,157 | 2,020 | 2.0 |
m8g.medium | arm64 | gp3-baseline | 1 | 4 | 16,670 | 249,555 | $0.0668 | ~$49 | 1.92 | 3.44 | 4.28 | 16,670 | 4,167 | 0.5 |
m7g.large | arm64 | gp3-baseline | 2 | 8 | 24,669 | 238,304 | $0.1035 | ~$76 | 1.30 | 2.83 | 3.58 | 12,334 | 3,084 | 0.7 |
r8g.medium | arm64 | gp3-baseline | 1 | 8 | 16,482 | 222,197 | $0.0742 | ~$54 | 1.94 | 3.51 | 4.29 | 16,482 | 2,060 | 0.5 |
m7g.2xlarge | arm64 | gp3-baseline | 8 | 32 | 77,197 | 221,629 | $0.3483 | ~$254 | 0.41 | 1.81 | 2.22 | 9,650 | 2,412 | 2.3 |
m8g.2xlarge | arm64 | gp3-baseline | 8 | 32 | 81,451 | 213,807 | $0.3810 | ~$278 | 0.39 | 1.75 | 2.13 | 10,181 | 2,545 | 2.5 |
c8i.large | x86-64 | gp3-max | 2 | 4 | 53,444 | 211,563 | $0.2526 | ~$184 | 0.60 | 2.17 | 2.83 | 26,722 | 13,361 | 1.6 |
c8i.xlarge | x86-64 | gp3-max | 4 | 8 | 69,067 | 199,429 | $0.3463 | ~$253 | 0.46 | 1.85 | 2.30 | 17,267 | 8,633 | 2.1 |
m8g.xlarge | arm64 | gp3-max | 4 | 16 | 67,428 | 199,242 | $0.3384 | ~$247 | 0.47 | 1.86 | 2.30 | 16,857 | 4,214 | 2.0 |
r8g.xlarge | arm64 | gp3-max | 4 | 32 | 69,292 | 188,322 | $0.3679 | ~$269 | 0.46 | 1.87 | 2.36 | 17,323 | 2,165 | 2.1 |
m5.xlarge | x86-64 | gp3-baseline | 4 | 16 | 39,959 | 186,794 | $0.2139 | ~$156 | 0.80 | 2.22 | 2.68 | 9,990 | 2,497 | 1.2 |
m7g.xlarge | arm64 | gp3-max | 4 | 16 | 57,738 | 179,252 | $0.3221 | ~$235 | 0.55 | 2.00 | 2.48 | 14,434 | 3,609 | 1.7 |
m7g.medium | arm64 | gp3-baseline | 1 | 4 | 10,986 | 175,171 | $0.0627 | ~$46 | 2.91 | 4.76 | 5.83 | 10,986 | 2,747 | 0.3 |
m7i.2xlarge | x86-64 | gp3-baseline | 8 | 32 | 73,190 | 172,163 | $0.4251 | ~$310 | 0.44 | 1.80 | 2.18 | 9,149 | 2,287 | 2.2 |
m5.large | x86-64 | gp3-baseline | 2 | 8 |