クラウドコスト最適化:MVPへの過剰な支払いをやめる
ほとんどのスタートアップはクラウド予算の40〜60%を無駄にしています。信頼性を犠牲にすることなくインフラストラクチャを適正化するための実践的なガイドです。

先日、あるスタートアップのAWS請求書を監査したところ、月額2,800ドルをインフラストラクチャに費やしていることが判明しました。これは900ドルで十分に運用できるものでした。彼らはt3.2xlargeでNode.js APIを実行しており、CPU使用率はピーク時で12%でした。3つの未使用のElastic IPがそれぞれ月額3.65ドルでアイドル状態でした。200行のデータベースにRDS Multi-AZデプロイメントを使用していました。無料でVPCエンドポイントを介することができたはずのトラフィックをNAT Gatewayがルーティングしていました。これらは悪意のあるものでも、特に不注意なものでもありませんでした。単に「とりあえず動くものをプロビジョニングする」という、リリースに向けたスプリント中に下された決定の積み重ねでした。
これは例外ではなく、むしろ一般的です。ほとんどの初期段階のスタートアップは、機能のリリースに追われ、コスト最適化に時間を割いたり、インセンティブを感じたりするチームメンバーがいないため、クラウド支出の40〜60%を無駄にしています。問題はさらに悪化します。一度インフラストラクチャがプロビジョニングされ、稼働し始めると、誰もそれを触らなくなります。
よく見られる最大のコストトラップ
解決策に入る前に、実際にお金がどこに使われているのかを理解することが役立ちます。これらは、スタートアップのインフラストラクチャをレビューする際によく遭遇する落とし穴です。
過剰にプロビジョニングされたコンピューティングインスタンス
これは最大の無駄の原因です。チームは初期設定時にインスタンスサイズを選択します。通常はブログ記事や「念のため」という考えに基づいており、その後見直すことはありません。私は、毎時間30秒間実行されるcronジョブをm5.xlargeインスタンスで実行しているのを見たことがあります。このインスタンスは59.5分間アイドル状態であり、実質的に何もせずに1時間あたり0.192ドル(月額140ドル)を消費しています。
根本的な原因は心理的なものです。誰もがサーバーのプロビジョニングを不足させて障害を引き起こした人物になりたくありません。そのため、誰もが多めに設定します。二重に。
# Check your EC2 instance CPU utilization over the past 2 weeks
aws cloudwatch get-metric-statistics \
--namespace AWS/EC2 \
--metric-name CPUUtilization \
--dimensions Name=InstanceId,Value=i-0abcdef1234567890 \
--start-time $(date -u -d '14 days ago' +%Y-%m-%dT%H:%M:%S) \
--end-time $(date -u +%Y-%m-%dT%H:%M:%S) \
--period 3600 \
--statistics Average Maximum
平均CPU使用率が20%未満で、ピークが50%未満の場合、ほぼ間違いなく過剰にプロビジョニングされています。インスタンスサイズを1つか2つ下げて、1週間監視し、調整してください。
忘れ去られたEBSボリュームとスナップショット
EC2インスタンスを終了しても、起動時に設定していない限り、アタッチされたEBSボリュームは自動的に削除されません。これは、終了されたインスタンスが、請求され続ける孤立したボリュームを残すことを意味します。私は、数十個の未アタッチのgp3ボリュームを持つアカウントを見たことがあります。それぞれが月額0.08ドル/GBかかり、誰も使用していないストレージに数百ドルが費やされていました。
スナップショットはさらに巧妙です。自動バックアップスクリプトは、ライフサイクルポリシーなしで毎日スナップショットを作成するため、無期限に蓄積されます。500GBのボリュームを1年間毎日スナップショットすると、365個のスナップショットが生成されます。EBSスナップショットは増分ですが、コストはかなりの金額になります。
# Find all unattached EBS volumes
aws ec2 describe-volumes \
--filters Name=status,Values=available \
--query 'Volumes[*].{ID:VolumeId,Size:Size,Created:CreateTime}' \
--output table
# Find snapshots older than 90 days
aws ec2 describe-snapshots \
--owner-ids self \
--query 'Snapshots[?StartTime<=`2025-12-01`].{ID:SnapshotId,Size:VolumeSize,Date:StartTime}' \
--output table
NAT Gateway:静かな予算キラー
NAT Gatewayは、存在するだけで1時間あたり0.045ドル(月額32.40ドル)かかり、さらに処理されるデータ1GBあたり0.045ドルがかかります。プライベートサブネットから外部サービスに頻繁にAPIコールを行うスタートアップの場合、データ処理料金だけで月額100ドルを超えることがあります。私は、小規模なスタートアップのAWS請求書全体の15〜20%をNAT Gateway料金が占めているのを見たことがあります。
解決策は、NATを通過するトラフィックの種類によって異なります。
- AWSサービス (S3, DynamoDB, SQS) へのトラフィック: VPC Gateway Endpoints (S3とDynamoDBは無料) または Interface Endpoints (それぞれ月額7.20ドルですが、大量のトラフィックではNATよりも安価) を使用します。
- Lambda関数からのインターネットへのトラフィック: それらの関数が実際にVPC内に存在する必要があるかどうかを検討してください。多くのLambda関数は、VPCリソースにアクセスしないにもかかわらず、「セキュリティのため」にVPC内に配置されています。
- 低ボリュームのアウトバウンドトラフィック: t4g.nano上のNATインスタンス(月額3.02ドル)は、NAT Gatewayのコストのほんの一部で控えめなトラフィックを処理できます。
データ転送料金
AWSは、リージョンから出るデータに対して1GBあたり0.09ドルを課金し、AZ間のトラフィックは各方向で1GBあたり0.01ドルかかります。これらの料金は、顕在化するまで目に見えません。3つのアベイラビリティゾーンにまたがるチャッティなマイクロサービスアーキテクチャで、サービスが毎秒数百回互いに呼び出し合う場合、驚くほどのデータ転送料金が発生する可能性があります。
アーキテクチャの修正策:非クリティカルなワークロードでは、頻繁に通信するサービスを同じAZに配置するか、AZアフィニティを持つ内部ロードバランサーを使用します。
適正化:体系的なアプローチ
適正化は一度きりの作業ではありません。四半期ごとに見直すべきものです。私が従うプロセスは次のとおりです。
ステップ1:利用状況データを収集する
AWS Compute Optimizerは無料で、EC2、EBS、Lambda、ECSの適正化に関する推奨事項を提供します。これを有効にし、推奨事項に基づいて行動する前に、少なくとも14日間のデータを収集させてください。
より詳細な分析には、CloudWatchメトリクスが主要なデータソースとなります。監視すべき主要なメトリクスは次のとおりです。
- EC2: CPUUtilization, NetworkIn/Out, MemoryUtilization (CloudWatchエージェントが必要)
- RDS: CPUUtilization, DatabaseConnections, FreeableMemory, ReadIOPS, WriteIOPS
- ElastiCache: CPUUtilization, CurrConnections, BytesUsedForCache
ステップ2:ワークロードを分類する
すべてのワークロードを同じ方法で適正化すべきではありません。私はそれらを3つのカテゴリに分類します。
定常状態のワークロード (APIサーバー、データベース): これらは一貫したキャパシティを必要とします。ピーク負荷を30%の余裕を持って処理できる最小のインスタンスを見つけて適正化します。ベースラインにはReserved InstancesまたはSavings Plansを使用します。
変動するワークロード (バッチ処理、ビルドサーバー): これらは適切なスケーリングポリシーを持つAuto Scaling Groups、またはフォールトトレラントなバッチジョブにはSpot Instancesを使用すべきです。
定期的なワークロード (cronジョブ、スケジュールされたレポート): これらは専用インスタンスで実行すべきではありません。Lambda、Fargate Spot、またはStep Functionsに移行します。
ステップ3:段階的に行動する
すべてを一度に適正化してはいけません。一度に1つのインスタンスサイズを下げ、1週間監視し、その後さらに進めるかどうかを決定します。短期間の過剰プロビジョニングのコストは、積極的なサイズダウンによって引き起こされる本番環境の障害のコストよりもはるかに低いです。
Reserved Instances vs Savings Plans vs Spot
ここで本当の節約が実現します。オンデマンド料金から30〜72%オフになりますが、コミットメントの仕組みが複雑なため、多くのスタートアップはこれらを完全に避けています。
Reserved Instances (RIs)
特定のリージョンの特定のインスタンスタイプに1年または3年間コミットします。その見返りとして、30〜40%オフ(前払いなし、1年)から60%オフ(全額前払い、3年)の割引を受けられます。注意点として、インスタンスタイプを変更する必要がある場合、Standard RIsは柔軟性がありません。Convertible RIsは、わずかに低い割引率(3年間の全額前払いで約45%)でより高い柔軟性を提供します。
RIsを使用するタイミング: データベースや、インスタンスタイプとサイズが本当に安定しているその他のワークロード。RDS Reserved Instancesはほとんどの場合、利用する価値があります。データベースのサイズはめったに変わりません。
Savings Plans
Savings Plansは、コンピューティングにおけるRIsの現代的な代替手段です。1時間あたりのコンピューティング使用量(例:1時間あたり0.10ドル)に1年または3年間コミットします。このコミットメントは、EC2、Fargate、Lambdaの使用量に自動的に適用され、インスタンスファミリー、サイズ、OS、リージョンをまたいで柔軟に対応します。
Savings Plansを使用するタイミング: コンピューティングワークロードの場合、EC2 RIsよりもほぼ常に優れています。Compute Savings Plansは、柔軟性と割引率の最適なバランスを提供します。最小限のベースライン支出をカバーするコミットメントから始めましょう。
# Example: Calculating Savings Plan commitment
# Current on-demand spend: $500/month on EC2
# Minimum baseline (never drops below): $350/month
# Recommended Savings Plan commitment: $350/month = ~$0.48/hour
# Expected savings: ~30% on the committed amount = ~$105/month
# Remaining $150/month stays on-demand for flexibility
Spot Instances
Spot Instancesは60〜90%の割引を提供しますが、2分間の通知で中断される可能性があります。これらは以下の用途に最適です。
- CI/CDビルドエージェント(複数のインスタンスタイプでSpot Fleetを使用)
- チェックポイントと再開が可能なバッチ処理ジョブ
- 開発およびステージング環境
- ロードテスト
これらは、本番APIサーバー、データベース、または突然の終了に対応できないものには適していません。
# Example: GitHub Actions self-hosted runner on Spot
# This saves roughly 70% compared to GitHub-hosted runners
# for compute-heavy builds
Resources:
SpotFleet:
Type: AWS::EC2::SpotFleet
Properties:
SpotFleetRequestConfigData:
IamFleetRole: !GetAtt SpotFleetRole.Arn
TargetCapacity: 2
AllocationStrategy: lowestPrice
LaunchSpecifications:
- InstanceType: c5.xlarge
SpotPrice: "0.06"
- InstanceType: c5a.xlarge
SpotPrice: "0.06"
- InstanceType: c6i.xlarge
SpotPrice: "0.06"
サーバーレスのコストモデル:常に安価とは限らない
サーバーレスはスタートアップにとって常に安価であるという根強い神話があります。小規模なうちは安価であることが多いですが、トラフィックが増加するにつれて経済性は変化します。
Lambdaの料金の現実
Lambdaはリクエストごと(100万リクエストあたり0.20ドル)と、コンピューティングのGB秒ごと(0.0000166667ドル)に課金されます。256MBメモリで200ms実行される典型的なAPIエンドポイントの場合:
- 1日あたり1,000リクエスト: 月額約0.03ドル。実質無料です。
- 1日あたり100,000リクエスト: 月額約3.00ドル。依然として非常に安価です。
- 1日あたり1,000,000リクエスト: 月額約30ドル。小規模なEC2インスタンスと比較できるレベルになり始めます。
- 1日あたり10,000,000リクエスト: 月額約300ドル。適切なキャッシングを備えたt3.medium(月額30ドル)であれば、これを容易に処理できます。
損益分岐点は実行時間とメモリ割り当てに大きく依存しますが、ほとんどのAPIワークロードでは、Lambdaは1日あたり100万〜500万リクエストの間でコスト効率が悪くなります。そのしきい値を下回る場合は、ほぼ常に最も安価なオプションです。
API Gatewayのコストは積み重なる
API Gatewayの背後にあるLambda関数には追加料金が発生することを人々は忘れがちです。API Gatewayは100万リクエストあたり3.50ドル(REST API)または100万リクエストあたり1.00ドル(HTTP API)かかります。大規模になると、API GatewayのコストがLambdaのコストを超えることがあります。Lambdaのコストを心配するほどのトラフィックを処理している場合は、API Gatewayの代わりにApplication Load Balancer(LCU時間あたり0.008ドル)を使用すべきです。
Fargate:中間点
AWS Fargateは、コストと運用上の複雑さの両方でLambdaとEC2の中間に位置します。インスタンス管理なしで、vCPUとメモリに対して秒単位で支払います。継続的に実行する必要があるが、サーバーを管理したくないワークロードの場合、Spot容量プロバイダーを備えたFargateは良いバランスを提供します。
0.25 vCPUと0.5GBメモリを持つFargateタスクを継続的に実行すると、月額約9ドルかかります。これはt4g.nanoと競合する価格であり、基盤となるホストを管理することなく、自動配置、ヘルスチェック、スケーリングが得られます。
コストのモニタリングとアラート
測定しないものは最適化できません。私がすべてのプロジェクトで設定するモニタリングスタックは次のとおりです。
AWS Cost Explorer
Cost Explorerを有効にし、50%、80%、100%のしきい値でアラートを設定した月次予算を設定します。これは最低限必要なことです。Cost Explorerの「サービス別コスト」ビューは、お金がどこに使われているかをすぐに示します。
# Create a budget with email alerts
aws budgets create-budget \
--account-id 123456789012 \
--budget '{
"BudgetName": "Monthly-Total",
"BudgetLimit": {"Amount": "500", "Unit": "USD"},
"TimeUnit": "MONTHLY",
"BudgetType": "COST"
}' \
--notifications-with-subscribers '[{
"Notification": {
"NotificationType": "ACTUAL",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 80,
"ThresholdType": "PERCENTAGE"
},
"Subscribers": [{
"SubscriptionType": "EMAIL",
"Address": "team@startup.com"
}]
}]'
Infrastructure as CodeのためのInfracost
Terraformを使用している場合、InfracostはCIパイプラインに統合され、インフラストラクチャの変更が適用される前に、そのコスト見積もりを表示します。これは革新的です。コスト意識を月ごとの驚きからプルリクエストの会話へと変えます。
# .github/workflows/infracost.yml
name: Infracost
on: pull_request
jobs:
infracost:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup Infracost
uses: infracost/actions/setup@v3
with:
api-key: ${{ secrets.INFRACOST_API_KEY }}
- name: Generate cost estimate
run: |
infracost breakdown --path=. \
--format=json --out-file=/tmp/infracost.json
infracost comment github \
--path=/tmp/infracost.json \
--repo=$GITHUB_REPOSITORY \
--pull-request=${{ github.event.pull_request.number }} \
--github-token=${{ secrets.GITHUB_TOKEN }}
コスト異常検出
AWS Cost Anomaly Detectionは、機械学習を使用して異常な支出パターンを特定します。これは無料で、支出が過去のパターンから逸脱した場合にアラートを送信します。各サービスでこれを有効にし、SlackへのSNS通知を設定してください。
節約につながるアーキテクチャパターン
個々のリソースの適正化を超えて、特定のアーキテクチャ上の決定はコスト構造を根本的に変えます。
積極的なキャッシング
キャッシュ可能なレスポンスのためにAPIの前にCloudFrontディストリビューションを配置すると、HTTPSリクエスト10,000件あたり0.085ドル、転送1GBあたり0.085ドルかかりますが、これらのリクエストがバックエンドに到達するのを防ぎます。読み取りが多いAPI(ほとんどがそうです)の場合、90%のキャッシュヒット率は、バックエンドが処理するトラフィックが10分の1になることを意味します。
さらに単純な方法として、Redisのようなインメモリキャッシュや、アプリケーション内のローカルLRUキャッシュを使用するだけで、冗長なデータベースクエリを排除できます。最も頻繁にアクセスされる5つのエンドポイントに15分間のキャッシュを追加した後、データベースコストが60%削減されたのを見たことがあります。
S3をインテリジェントに利用する
S3には複数のストレージクラスがあり、適切なものを使用することが重要です。
| ストレージクラス | コスト/GB/月 | ユースケース |
|---|---|---|
| S3 Standard | $0.023 | アクティブデータ、頻繁なアクセス |
| S3 Infrequent Access | $0.0125 | バックアップ、30日以上前のログ |
| S3 Glacier Instant | $0.004 | 即時アクセスが必要なアーカイブ |
| S3 Glacier Deep Archive | $0.00099 | 長期アーカイブ、まれなアクセス |
S3ライフサイクルポリシーを設定して、オブジェクトをストレージクラス間で自動的に移行させます。
{
"Rules": [
{
"ID": "TransitionToIA",
"Status": "Enabled",
"Transitions": [
{
"Days": 30,
"StorageClass": "STANDARD_IA"
},
{
"Days": 90,
"StorageClass": "GLACIER_INSTANT_RETRIEVAL"
}
]
}
]
}
マネージドサービス vs セルフホスティング
このトレードオフは微妙です。マネージドサービス(RDS、ElastiCache、OpenSearch Service)は、EC2でセルフホスティングするよりもコンピューティング単位あたりのコストは高くなりますが、パッチ適用、バックアップ、フェイルオーバー、モニタリングが含まれています。専任の運用担当者がいないスタートアップにとって、節約されるエンジニアリング時間は、ほとんどの場合、プレミアムを正当化します。
例外は、最高ティアのマネージドサービスです。db.r6g.2xlargeのRDSインスタンスは、同等のEC2インスタンスでPostgreSQLを実行するよりも大幅に高価です。運用能力のあるチームがあり、単一のマネージドサービスに月額1,000ドル以上を費やしている場合は、セルフホスティングを検討する価値があります。
可能な限り統合する
ステージング、QA、開発環境用に個別のRDSインスタンスを実行するのは高価です。選択肢は次のとおりです。
- 非本番環境用に、個別のデータベースを持つ単一のRDSインスタンスを使用する。
- 開発/ステージングにはAurora Serverless v2を使用する。アイドル時にはゼロにスケールします。
- 開発データベースをDockerを搭載した単一のEC2 Spot Instanceで実行する。
実践的なコスト最適化プレイブック
コスト最適化プロジェクトに取り組む際に私が従うステップバイステップのプロセスです。これは通常、最初の1ヶ月で30〜50%の節約を達成します。
1週目:監査
- AWS Cost Explorerがまだ有効になっていない場合は有効にする。
- サービス別の3ヶ月間のコスト内訳を取得する。
- 支出額上位5つのサービスを特定する。
- AWS Compute OptimizerとTrusted Advisorを実行する。
- 未アタッチのEBSボリューム、未使用のElastic IP、アイドル状態のロードバランサーをすべてリストアップする。
2週目:クイックウィン
- 監査で特定された未使用のリソースを削除する。
- 最も過剰にプロビジョニングされたインスタンスを適正化する(1サイズ下げて監視)。
- S3およびDynamoDBトラフィック用のVPCエンドポイントを設定する。
- すべてのバケットでS3ライフサイクルポリシーを有効にする。
- 予算アラートを設定する。
3週目:コミットメント
- 定常状態のワークロードについてSavings Planの対象となるか分析する。
- ベースラインのコンピューティング支出に対してCompute Savings Plansを購入する。
- 本番データベース用にRDS Reserved Instancesを購入する。