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-8EC2:毎週1~2インスタンスずつ変更→各変更後2週間CloudWatchで監視・RDS:レプリカ構成見直し&インスタンスタイプ変更
3ヶ月目Week 9-12Lambda 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万円削減できたけど、チーム内では「これで終わりじゃない」という認識です。個人的には、ここからが本当の勝負だと思ってる。

次のフェーズは:

  1. Reserved Instancesの最適化:Compute Optimizerでサイジングした後、RI購入を自動化。さらに30~40%削減の可能性がある。ただし購入タイミングが難しい。

  2. Savings Plansの活用:Compute Optimizerと組み合わせてSavings Plans購入のタイミングを自動判定。RIより柔軟だから本番環境向け。

  3. スポットインスタンスの本番活用:非本番環境だけじゃなく、バッチ処理にスポット導入で追加削減。トラブルの可能性あるけど、価値がある。

  4. 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の自動化。また新しく学んだことがあれば、また書きますね。

U

Untanbaby

ソフトウェアエンジニア|AWS / クラウドアーキテクチャ / DevOps

10年以上のIT実務経験をもとに、現場で使える技術情報を発信しています。 記事の誤りや改善点があればお問い合わせからお気軽にご連絡ください。

関連記事