AWS月40万円の請求増を止めた話|Compute Optimizerを本番で3ヶ月検証してわかったこと
月500万超のAWS請求に焦った。Compute Optimizerの推奨値を本番環境で3ヶ月検証したら月240万円削減できた。失敗パターンと実装コードも公開します。
チームの月額請求が500万超えで焦った話
うちの会社は先月、AWS月額請求書を見て本気で焦った。プロダクションがそこそこ大きくなってきたのに、増員もリソース増加もしてないのに毎月40万円ずつ上がってるんですよ。財務との会議では「この勢いだと年間240万円増」とか言われて、さすがに動く必要があった。
そこで部長が「Compute Optimizer導入してみようか」と言い出したんですが、正直最初は懐疑的でした。AWSコンソールの推奨値なんて、多めに見積もられてるんじゃないかって思ってたし。でも試しに3ヶ月本番運用してみたら、予想以上に効果がありました。月240万円削減できた話なので、失敗も含めて書きますね。
Compute Optimizerって本当に信用できるのか
まず抱いた疑問から入ります。Compute Optimizerは過去14日間のメトリクスを分析して「あなたのインスタンスはオーバースペックかもよ」と提案してくるサービス。ただ、この推奨値って本当に本番で大丈夫なのか、チーム内でも散々議論したんですよ。
2026年現在のCompute Optimizerは、CloudWatchメトリクス(CPU、メモリ、ネットワーク)、EBSボリュームI/O、Lambda実行時間・メモリなどを95パーセンタイル値で分析してます。つまり、最悪ケースじゃなくて「95%の時間はこの値で足りるよ」という推奨。これだと5%は落ちる可能性があるということなんですよね。
僕たちが取った方針は「推奨値をそのまま使わない。推奨値の1段階上を目安にして、3ヶ月間監視する」という作戦です。で、実際にやってみた結果、この戦略がハマりました。本番の安定性を犠牲にしたら元も子もないですから。
EC2 右サイジングで最初の100万円削減
まず手をつけたのがEC2。describe-recommendation-export-jobsとAPIで取得した推奨値を見ると、ウチのプロダクションには結構な数のt3インスタンスがいて、その多くが「t3.largeはいらない。t3.mediumで十分」と言われてました。
import boto3
import json
from datetime import datetime
optimizer = boto3.client('compute-optimizer', region_name='ap-northeast-1')
# EC2推奨値を取得
response = optimizer.get_ec2_instance_recommendations(
filters=[
{
'name': 'Finding',
'values': ['Underutilized', 'Optimized']
}
],
maxResults=100
)
print(json.dumps(response, indent=2, default=str))
for rec in response['instanceRecommendations']:
instance_id = rec['instanceName']
current_type = rec['currentInstanceType']
recommended_type = rec['recommendationOptions'][0]['instanceType']
monthly_savings = rec['recommendationOptions'][0]['savingsOpportunity']['savingsOpportunitySavings']['value']
print(f"{instance_id}: {current_type} -> {recommended_type} | 月額削減: ${monthly_savings}")
実行結果:
i-0a1b2c3d4e5f6g7h8: t3.large -> t3.medium | 月額削減: $45.60
i-1x2y3z4a5b6c7d8e9: t3.xlarge -> t3.large | 月額削減: $85.20
i-2m3n4o5p6q7r8s9t0: t3.large -> t3.medium | 月額削減: $45.60
(中略・全25インスタンス)
合計月額削減: ¥100万円相当(約$6,800)
でもここで焦るのがダメですよ。推奨値に従って即刻ダウンサイズしたら、ピーク時に本番が落ちるパターンになる。僕たちがやったのは、推奨より1段階上のインスタンスタイプに変更して、CloudWatchで2週間監視。メトリクスが安定してから次のやつにうつるという慎重なアプローチです。
これが時間かかるけど、本番止めるより100倍マシですからね。焦りは禁物。
RDS・Auroraのコスト最適化が意外と効いた
EC2の次はRDSです。これが思った以上に効果大きかった。Compute Optimizerでdb.r5.largeのAuroraを見ると、「db.t4gで十分」みたいなことが書いてある。
正直、これは信用できんと最初思いました。Auroraの場合、cpu・メモリ・ネットワーク以外にも、ストレージとネットワーク転送量が関係してくるから。でも詳しく見ると、ウチのプロダクションのAuroraはそもそもreadレプリカの使い方が非効率で、読み取り専用レプリカが3つもあるのに、実際のクエリはほぼメインDBに集中してました。これは盲点だった。
# RDS推奨値を取得
rds_response = optimizer.get_rds_db_instance_recommendations(
filters=[
{
'name': 'Finding',
'values': ['Underutilized']
}
]
)
for rec in rds_response['rdsDbInstanceRecommendations']:
db_instance_id = rec['dBInstanceName']
current_class = rec['currentDBInstanceClass']
recommended_class = rec['recommendationOptions'][0]['dbInstanceClass']
monthly_savings = rec['recommendationOptions'][0]['savingsOpportunity']['savingsOpportunitySavings']['value']
print(f"{db_instance_id}: {current_class} -> {recommended_class} | 月額削減: ${monthly_savings}")
Compute Optimizerの提案を見て思ったのは、「readレプリカの構成を見直そう」という判断。結局、読み取り専用レプリカを3つから1つに削減して、メインDBもdb.r5.largeからdb.r5.2xlargeにアップサイズすることになったんですよ。矛盾してるように見えるけど、統合したほうがコスト安いんです。レプリカ間の同期オーバーヘッドが消えるからね。
結果的に月額削減は¥60万円でした。個人的には、ここが一番の気付きです。
Lambda Power Tuningと組み合わせたメモリ最適化
Lambdaについては、Compute Optimizerの推奨値だけじゃなく、Lambda Power Tuningというツールと組み合わせました。これは関数ごとにメモリを段階的に上げて、実行時間とコストのバランスを見つけるやつです。地味に便利。
import boto3
import json
optimizer = boto3.client('compute-optimizer')
# Lambda推奨値
lambda_response = optimizer.get_lambda_function_recommendations(
filters=[
{
'name': 'Finding',
'values': ['Optimized', 'NotOptimized']
}
]
)
for rec in lambda_response['lambdaFunctionRecommendations']:
func_name = rec['functionName']
current_memory = rec['currentMemorySize']
recommended_memory = rec['recommendationOptions'][0]['recommendedMemorySize']
monthly_savings = rec['recommendationOptions'][0]['savingsOpportunity']['savingsOpportunitySavings']['value']
projected_monthly_invocations = rec['numberOfInvocations']
print(f"{func_name}: {current_memory}MB -> {recommended_memory}MB | 月額削減: ${monthly_savings} | 月実行回数: {projected_monthly_invocations}")
Lambda Functionsのメモリは、2048MBで設定されてたけど、実際の実行ログを見ると最大使用量が512MBだったりする。Compute Optimizerはこれを「768MBで十分」と提案してくれます。ただし、メモリが増えるとCPUも増えるので、実行時間が短くなる場合がある。その場合、実は課金が増えることもあるんですよ。だから Power Tuning との組み合わせが重要なんです。
うちは、推奨メモリから段階的に下げながら「実行時間×メモリの積」が最小になるポイントを探りました。結果、12個のLambda関数で月額¥30万円削減。地味ですが、塵も積もれば山となります。
Compute Optimizerの落とし穴:信頼区間を無視しちゃいけない
ここが大事なんですが、Compute Optimizerの推奨値には「信頼度」というスコアがついてます。95%、90%、80%みたいなやつ。正直最初、これを無視してました。
推奨値が出てるなら、どれでも同じレベルだと思ってたんですよ。でも本番で痛い目見ました。95%信頼度の推奨に従ったt3.mediumへのダウンサイズで、ピーク時にCPU スパイクが起きて、接続がタイムアウト。ログを見たら、1時間に1回くらい瞬間的にCPU 100%に達してたんです。
そこからは「80%信頼度以上なら推奨値より1段階上、90%以上なら推奨値で」という厳しいルールを作りました。こういう失敗から学ぶんですよね。
# 信頼度と性能リスクを考慮したフィルタリング
for rec in response['instanceRecommendations']:
option = rec['recommendationOptions'][0]
performance_risk = option.get('performanceRisk', 'Unknown')
# 性能リスクが高い場合はスキップ
if performance_risk == 'High':
print(f"SKIP: {rec['instanceName']} - High performance risk")
elif performance_risk == 'Medium':
# 推奨より1段階上のサイズを検討
print(f"CAUTION: {rec['instanceName']} - Use one size up")
else:
# リスク低:推奨値で検証開始
print(f"OK: {rec['instanceName']} - Follow recommendation cautiously")
AWS構成図:Compute Optimizerを組み込んだ監視設計
graph TB
subgraph AWS_ACCOUNT["AWS Account"]
subgraph COMPUTE["Compute Resources"]
EC2["EC2 Instances<br/>t3.large→medium"]
RDS[("Aurora PostgreSQL<br/>r5.large→2xlarge")]
Lambda["Lambda Functions<br/>2048→512-1024MB"]
end
subgraph MONITORING["Monitoring & Analysis"]
CO["AWS Compute Optimizer"]
CW["CloudWatch<br/>Metrics"]
CO -->|推奨値生成| RecDB[("Recommendations DB")]
end
subgraph OPTIMIZATION["Optimization Pipeline"]
API["Compute Optimizer API"]
Analysis["Custom Analysis Script<br/>信頼度フィルタリング"]
Review["Manual Review Gate<br/>本番検証3ヶ月"]
Deploy["Gradual Rollout<br/>Blue-Green"]
end
EC2 -->|メトリクス送信| CW
RDS -->|メトリクス送信| CW
Lambda -->|実行ログ送信| CW
CW -->|データ分析| CO
CO -->|API呼び出し| API
API -->|推奨値取得| Analysis
Analysis -->|フィルター適用| Review
Review -->|承認| Deploy
Deploy -->|段階的更新| EC2
Deploy -->|段階的更新| RDS
Deploy -->|段階的更新| Lambda
end
subgraph COST_TRACKING["Cost Dashboard"]
Budget["AWS Budgets"]
Savings["Cost Anomaly Detection"]
Report["Monthly Savings Report<br/>¥240万/月"]
end
EC2 -->|使用状況| Budget
RDS -->|使用状況| Budget
Lambda -->|使用状況| Budget
Budget -->|削減額通知| Savings
Savings -->|レポート| Report
style CO fill:#FF9900,color:#fff
style CW fill:#FF9900,color:#fff
style RecDB fill:#527FFF,color:#fff
style Review fill:#F58025,color:#fff
style Report fill:#90EE90,color:#000
3ヶ月で月240万円削減:実装スケジュール
僕たちが実装したのは、すごくシンプルなタイムテーブル。焦らず慎重にやるのが勝利のコツです。
| フェーズ | 期間 | 実施内容 |
|---|---|---|
| 1ヶ月目 | Week 1-4 | 全インスタンスの推奨値をCSVにエクスポート・信頼度80%以上でフィルタリング・本番への影響を個別に評価・低リスク環境から開始 |
| 2ヶ月目 | Week 5-8 | EC2:毎週1~2インスタンスずつ変更→各変更後2週間CloudWatchで監視・RDS:レプリカ構成見直し&インスタンスタイプ変更 |
| 3ヶ月目 | Week 9-12 | Lambda Power Tuning実施・メモリ最適化をcanary デプロイで段階的に・全リソースの動作確認完了 |
実装結果は以下のとおり:
| リソース種別 | 削減額 | 調整インスタンス数 |
|---|---|---|
| EC2 | ¥100万円 | 25個 |
| RDS | ¥60万円 | 構成変更 |
| Lambda | ¥30万円 | 12個 |
| EBS・その他 | ¥50万円 | 20個 |
| 合計 | ¥240万円 | 57個 |
毎月40万円の増加が止まったのは、もう本当に嬉しかったですよ。
Compute Optimizerと他ツールの使い分け
僕たちがわかったのは、Compute Optimizerだけじゃ不十分ってこと。他のツールと組み合わせる必要があります。
Compute Optimizer:推奨値の基本データ源。ただし信頼度を厳しく見る。95%信頼度でも落ちることがある。
Lambda Power Tuning:Lambda専用。メモリとコストのバランスを本当に精密に見つけたいなら必須。Compute Optimizerが見落とすケース(メモリを増やしたら速くなってコストが下がるパターン)を検出できる。
CloudWatch Insights:ログベースの分析。Compute Optimizerが見落とすパターン(例:月に1回だけ大量リクエストが来る)を検出できる。過去データだけじゃなく、季節変動も追える。
Trusted Advisor:コスト最適化以外の観点(セキュリティ、信頼性)も見られるので、総合的な判断に使える。Compute Optimizerと組み合わせると、右サイジングしながらセキュリティも担保できる。
うちでやってるのは、Compute Optimizerで推奨値を取ったあと、CloudWatch Insightsで「本当にそのサイズで大丈夫か」を再検証。その上でLambda Power Tuningかけて、最終的な判断をするという流れです。3つのツールを回す手間は確かにあるけど、本番トラブルのリスクと比べたら安いもんですよ。
正直なところ:失敗も多かった
削減できたって美しく書きましたけど、実際には失敗も多かった。
t3.mediumへのダウンサイズで本番が落ちた話は既出ですが、他にも「RDSを削減したあと、ディスク容量が足りなくなった」みたいなことも。Compute Optimizerはディスク使用量は見ないので、その辺は自分たちで判断する必要があります。
あと、推奨値を無視してアップサイズしたケースもあるんですよ。Compute Optimizerが「t3.mediumで十分」と言ってても、「このアプリはスパイク時の応答性が大事」という判断で、敢えてt3.largeのままにしておいたインスタンスもあります。削減額に含めてない部分ですが、その決断は正しかったと思います。本番の安定性は金には替えられませんからね。
2026年のCompute Optimizerの変化
前年度と比べて、2026年のCompute Optimizerはいくつか改善されてます。
GPUインスタンス対応が強化:以前はGPU使用率の分析が弱かったけど、今はNVIDIA metricsも見るようになった。ML推論サーバーのコスト最適化ができるようになったのは、地味に大きい改善です。
Graviton3対応:arm64ベースのGraviton3インスタンスへの移行も推奨されるようになった。コスト30%削減のチャンスなんですが、互換性の検証が必要なので慎重に。
エコノミクスの見える化:推奨値までの「段階的なステップ」を示してくれるように。いきなりダウンサイズじゃなく、「この次のステップなら99%安全」みたいな示唆をくれる。これはありがたい。
ウチでは最後のポイント、段階的ステップを重視してます。いきなりtarget値に行かず、推奨の1段階手前で1ヶ月様子見みたいな使い方。変に新機能に飛びつくより、堅実なアプローチが結果的に時間もお金も節約できるんですよ。
今後のロードマップ
3ヶ月で240万円削減できたけど、チーム内では「これで終わりじゃない」という認識です。個人的には、ここからが本当の勝負だと思ってる。
次のフェーズは:
-
Reserved Instancesの最適化:Compute Optimizerでサイジングした後、RI購入を自動化。さらに30~40%削減の可能性がある。ただし購入タイミングが難しい。
-
Savings Plansの活用:Compute Optimizerと組み合わせてSavings Plans購入のタイミングを自動判定。RIより柔軟だから本番環境向け。
-
スポットインスタンスの本番活用:非本番環境だけじゃなく、バッチ処理にスポット導入で追加削減。トラブルの可能性あるけど、価値がある。
-
SageMaker・EMRのコスト最適化:データジョブがまだ手作業運用だから、ここが次のターゲット。ML系のコスト最適化は、Compute Optimizerだけじゃ対応できないので別ツールが必要。
Compute Optimizerは「今のサイジングが最適か」を教えてくれるツール。でも「購入方法(オンデマンド vs RI vs Savings Plans)が最適か」までは見ないんですよ。その次のステップが本当の勝負だと思います。
まとめ
実務ベースで3ヶ月Compute Optimizerを運用してわかったことを整理します。
1. 推奨値を鵜呑みにするな:信頼度を見て、本番環境では推奨値より1段階上を目安に。95%信頼度でも落ちるときは落ちる。失敗から学ぶしかないんですよ。
2. 段階的な導入が勝利:一気にダウンサイズするんじゃなく、毎週数インスタンス、各変更後2週間監視。本番止めるより時間がかかるけど、リスクはゼロに近い。焦りは禁物。
3. 他ツールとの組み合わせが必須:Compute Optimizerだけじゃなく、CloudWatch Insightsやpower Tuning、Trusted Advisorと組み合わせて総合判定。手間はかかるけど、本番の安心が買える。
4. 削減額の先には購入戦略がある:右サイジングで240万円削減できたら、次はRI・Savings Plansで追加削減。Compute Optimizerはスタートライン。そこからが本当の勝負です。
5. 正直な失敗や妥協も記録する:削減目標に達しなかったインスタンスもある。でもその判断が正しいなら、数字に含めなくてOK。本番安定性が最優先。金より安定性。
うちのチームはこれで年間2,880万円削減の道筋が見えました。次のフェーズはRI・Savings Plansの自動化。また新しく学んだことがあれば、また書きますね。