目次
- はじめに
- Web 3層構成(ALB + EC2 + RDS)
- コンテナ構成(ECS Fargate)
- サーバーレス構成(API Gateway + Lambda)
- データ分析基盤(S3 + Athena / Glue)
- CDN構成(CloudFront + S3 / ALB)
- マルチアカウント構成(AWS Organizations)
- まとめ:設計フェーズで問うべきこと
はじめに
AWSのコスト最適化について書かれた記事の多くは、
システム利用開始後のコスト削減の余地について、Cost Explorerで分析し、
それに対してSavings Plan購入や不要リソース削除、アーキテクチャの見直しなどを提案するような記載が多い。
それ自体は有用だが、「後からの最適化」だけでなく、
「コストを意識した設計を最初から行う」というのも同じぐらい重要である。
とはいえ、とりわけコストにおいては最初から設計を完璧に決め切ることはできない。
実際のトラフィックパターンは予測と異なるし、機能追加でアーキテクチャも変化する。
そのため 「最初に正しく作る」ことに加えて、「運用しながら改善できる仕組みを最初から組み込む」 ことも重要になってくる。
当記事では、 第一部(本稿) で、代表的な6つの構成パターンでコストが膨らみやすい設計判断とその判断軸を整理する。
第二部 では、運用フェーズでコストの異常に気づき、調査し、改善に繋げるための「コスト・オブザーバビリティ」の仕組みを扱う。設計と運用の両輪が揃って初めて、継続的なコスト最適化が機能する。
1. Web 3層構成(ALB + EC2 + RDS)
Web 3層構成はAWSでは教科書的な構成だ。
AWSを学び始めると、まず最初に触れる構成といっても過言ではない。
シンプルで理解しやすいが、「とりあえず動かす」で設計すると、設計判断のひとつひとつがじわじわとコストに効いてくる。
EC2のインスタンスタイプを最初に決めたまま変えない
最初に選んだインスタンスタイプが、そのまま本番運用に入るケースは多い。
「ピーク時の負荷を考えて大きめに」という判断自体は自然だが、問題になってくるのはその後である。
❌ よくある状況
m5.2xlargeを余裕を持って選択。ピーク対応はできているが、平常時のCPU使用率は10〜20%前後で推移。スケーリングの仕組みも入れていないため、ピーク時間帯以外も同じコストが発生し続けている。
Auto Scalingを導入すれば解決するように見えるが、話はそう単純ではない。RDSとの接続数問題(スケールアウト時に接続が急増する)やセッション管理の設計を先に考えておかないと、後からAuto Scalingを入れることが難しくなる。スケーリングを前提にしない設計を初期に固めてしまうと、後からのコスト最適化の選択肢が大きく狭まることになる。
RDS Multi-AZをすべての環境に一律適用する
Multi-AZは本番環境では必要な選択だ。しかし開発・ステージング環境にも同じ設定を適用しているケースは珍しくない。Multi-AZはスタンバイインスタンスを常時起動しておく設計なので、コストは単純に約2倍になる。
| コスト側の問題 | そう設計する理由 |
|---|---|
| ステージングでもRDSコストが実質2倍 | 本番と同構成にして設定ミスを防ぎたい |
| フェイルオーバー不要な環境でも払い続ける | ステージングでも継続性テストをしたい |
| スナップショット・バックアップコストも加算 | 環境ごとに設定復元、即時リカバリができるようにしたい |
運用側の気持ちもわかるが、そのコストをかけてまで、本番と同等の環境を複数維持する必要があるのか、事前に検討しておくべきである。
もしステージングの目的が「機能検証」であれば、Single-AZ+縮小インスタンスで十分なことがほとんどだ。
EBSボリュームを過大にプロビジョニングしたまま放置する
EC2にアタッチするEBSボリュームも、インスタンスタイプと同じ「最初に決めたまま変えない」罠にはまりやすい。ボリュームサイズは使用率に関わらず確保した容量全体が課金対象になる。
❌ よくある状況
ログやファイルの一時保存用に
gp2で1TBを確保。実際の使用量は200GB前後で推移しているが、縮小するには手順が面倒なため放置されている。加えてgp2のまま運用しているため、同容量でも20%程度安いgp3への移行機会を逃している。
EBSは gp2 から gp3 への変更がコンソール・CLIから無停止で行える。パフォーマンス要件が同等であれば gp3 の方が安く、スループットとIOPSも独立して設定できる。サイジングの見直しと合わせて、ボリュームタイプの棚卸しも定期的に行う価値がある。
ALBを開発・検証環境に残したまま消し忘れる
ALBはリクエストがゼロでも時間課金が発生する(約0.026USD/時間、東京リージョン)。月換算で約19USD程度だが、開発・検証環境のALBを複数放置していると、それだけで月数千円〜数万円の固定費になる。
⚠️ 見落としやすい状況
検証目的で構築したALBをそのままにして次のタスクへ移る。「使っていないから課金されていないはず」という誤解がある。ALBに限らず、NAT Gateway・Elastic IP・RDSインスタンスも同様にアイドル課金が発生し続ける。
判断軸
- ステージング環境の目的が「機能検証」なら Single-AZ+一回り小さいインスタンスで十分
- Auto Scalingを使う予定があるなら、RDS Proxyの要否を設計の最初に検討しておく。ただしRDS Proxy自体もvCPU数に対して課金される(東京リージョンで0.015USD/vCPU時間程度)。たとえば
db.t3.medium(2 vCPU)では月約22USDの追加コストになるため、Proxyを入れることでEC2のスケールアウトが可能になり削減できるコストと比較したうえで判断する - インスタンスサイジングは、Compute Optimizerの推奨事項を導入後に定期確認する運用を行う
- EBSは定期的にボリュームタイプ(
gp2→gp3など)の見直しとサイズの棚卸しをする - 開発・検証環境のリソースは「使い終わったら消す」をルール化する。場合によってはネーミングルールを定義のうえ、不要リソースを定期的に自動削除する
2. コンテナ構成(ECS Fargate)
Fargateはインスタンス管理を不要にしてくれる。その代わり、タスク定義で指定するCPU・メモリが課金の直接の単位になる。EC2のように「使用率に関係なく起動しているだけでコストがかかる」のと同じ構造が、タスク単位で発生する。
タスクサイズを「安全マージン込み」で設定したまま放置する
Fargateのタスクサイズ(CPU/メモリの組み合わせ)は、タスク定義の時点で固定される。問題は、その数字が実際のワークロードに合っているかどうかを、後から確認しないことだ。
❌ よくある状況
1 vCPU / 2GBのタスクを定義したが、実際の使用率はCPU 5〜10%、メモリ 400MB前後。「Fargateはサーバーレスだから効率的なはず」と思い込み、Container Insightsで確認していなかった。0.25 vCPU / 512MBでも動作する可能性が高いが、変更には再デプロイが必要なため後回しになっている。
Fargateのタスクサイズは 0.25 vCPU / 512MB から始められる。最小構成で動作検証してから上げていく習慣をつけておけば、後から「削減のために再設計する」という作業が不要になる。
📝 実際の使用率を確認するには
タスク単位のCPU・メモリ使用率を把握するにはContainer Insightsの有効化が必要だ。デフォルトのCloudWatchメトリクスで取得できるのはサービス全体の平均値にとどまり、「定義したタスクサイズに対して何%使っているか」という粒度では確認できない。ただしContainer Insights自体にも課金(CloudWatchカスタムメトリクス料金+ログ収集料金)が発生するため、大規模環境では有効化するクラスターを絞ることも検討する。詳細は第二部のメトリクス設計で触れる。
NAT Gateway経由でECRイメージをpullし続けている
FargateタスクがECRからコンテナイメージをpullするとき、デフォルトではNAT Gatewayを経由する。NAT Gatewayは通過するデータ量ごとに課金されるため(0.062USD/GB、ap-northeast-1〈東京〉の場合)、デプロイ頻度が高い環境では見落としがちなコストが積み上がる。
⚠️ 試算例
1GBのECRイメージを1日50回デプロイすると、NAT Gatewayのデータ処理コストだけで月93USD程度。1日100回なら月186USD程度。これはNAT Gateway自体の稼働コストとは別に発生する。
ECR・S3・CloudWatch Logs向けのVPCエンドポイントを設置することで、これらのトラフィックはNAT Gatewayを経由しなくなる。
タスクにパブリックIPv4アドレスを自動アサインしている
2024年2月から、EC2インスタンスやFargateタスクに割り当てるパブリックIPv4アドレスが有料になった(0.005USD/時間/個)。Fargateタスクにパブリックサブネットを使いつつパブリックIPを自動アサインしている構成は、タスク数×時間でそのままコストになる。
また、セキュリティの観点でも、ECSサービスにはパブリックIPアドレスを自動で割り当てないことが推奨される。
⚠️ 試算例
常時10タスク稼働している場合、パブリックIPアドレスだけで月36USD程度(0.005USD × 730時間 × 10個)の追加コストが発生する。
AssignPublicIpをDISABLEDに設定し、ALBをフロントに置く構成であればタスク自身がパブリックIPを持つ必要はない。
ステージング環境のタスク最小数を本番と同じにしている
ECSサービスの最小タスク数(desiredCount の下限)を本番と揃えている場合、ステージング環境でもトラフィックがゼロの時間帯に複数タスクが起動し続ける。Fargateはタスクが起動している時間だけ課金されるため、最小タスク数の設計は直接コストに効く。
✅ 設計のポイント
ステージング環境のECSサービスは、業務時間外にタスク数をゼロにするスケジュールを設定しておくと、夜間・休日のコストをほぼゼロにできる。EventBridge Schedulerを使って「平日9〜18時のみ稼働」にするだけで月のコストを大幅に削減できる。
判断軸
- タスクサイズは最小構成で動かして実測してから上げる。最初から大きく取る理由はない
- ECR・S3・CloudWatch Logs向けのVPCエンドポイントは、Fargate採用時のデフォルト設計として最初から含める
- プライベートサブネット+VPCエンドポイント構成にすることでパブリックIPアドレス課金を回避できる
- ステージング環境はEventBridge Schedulerで業務時間外のタスクをゼロにすることを検討する
- Fargate Spotは中断を許容できるバッチ処理やジョブに限定して使う。常時稼働サービスへの適用は慎重に
3. サーバーレス構成(API Gateway + Lambda)
Lambdaは「リクエスト数が少ないときに圧倒的に安い」サービスだ。しかし、その安さには前提条件がある。リクエスト頻度が上がるにつれて、EC2やFargateとのコスト差が縮まり、やがて逆転するポイントが存在する。
高頻度呼び出しでFargateよりコストが高くなる
Lambdaの料金は、リクエスト数 × 実行時間 × メモリで決まる(0USD.0000166667/GB秒、ap-northeast-1〈東京〉の場合)。これを具体的な数字で試算してみよう。
試算:月1億リクエスト・200ms・512MB
Lambda(x86、東京リージョン)
リクエスト料金:0.20USD × 100 = 20USD
コンピュート:100,000,000 × 0.2s × 0.5GB × 0.0000166667USD = 167USD
合計:約 187USD / 月
Fargate(常時2タスク・0.5vCPU/1GB、東京リージョン)で同等のスループット処理
2タスク × 0.05056USD/vCPU時間 × 0.5vCPU × 730時間 ≈ 37USD
2タスク × 0.00553USD/GB時間 × 1GB × 730時間 ≈ 8USD
合計:約 45USD / 月
この条件では、LambdaはFargateの4倍以上のコストになる。もちろん「Fargateが常に2タスク稼働してトラフィックを処理できる」という前提が成り立つかどうかは、ピーク時の同時実行数によって変わる。Lambdaにはバースト対応力という優位性があり、一概にどちらが良いとは言えない。ただ、「サーバーレスだから安い」は高頻度・常時負荷のワークロードには当てはまらない ことは設計前に確認しておく必要がある。
📝 2025年8月の課金変更
2025年8月からLambdaはINIT(コールドスタート)フェーズも課金対象になった(ZIPパッケージ+マネージドランタイムの組み合わせに対して、以前は無料だった初期化フェーズが課金される)。低トラフィックで頻繁にコールドスタートが発生する関数は、INITフェーズの割合が大きいほど以前よりコストが増加している可能性がある。2025年8月以降の請求を確認していない場合は、Lambda Power TuningやCloudWatch Logs Insightsで現状を把握することを勧める。
Provisioned Concurrencyを「つけっぱなし」にしている
コールドスタートのレイテンシ問題を解決するために Provisioned Concurrency を設定するのは理にかなっている。ただし、通常の Lambda と比較して単価が約58%高い(0.0000097222USD/GB秒)うえに、実行の有無に関係なく課金が発生する。
⚠️ 見落としやすいコスト構造
Provisioned Concurrencyは「アイドル時間にも通常より高い単価で課金される」という二重の意味でコストが重い。たとえば 512MB × 10並列で確保した場合、実行ゼロの時間帯でも月15USD程度のアイドルコストが発生する。通常のオンデマンドLambdaとは異なる課金構造であることを意識しておく必要がある。
REST APIとHTTP APIを使い分けていない
API GatewayにはREST APIとHTTP APIの2種類がある。料金が大きく異なるが、「API Gatewayといえばとりあえずコンソールのデフォルト」でREST APIを選んでいるケースが多い。
HTTP APIはREST APIと比べて最大71%安い。単純なLambdaプロキシ用途であればHTTP APIで十分なことがほとんどだ。
📊 コスト比較(月1億リクエストの場合)
APIタイプ 単価 月額 REST API 3USD.50 / 百万リクエスト 350USD HTTP API 1USD.00 / 百万リクエスト 100USD 同じ用途でREST APIを選ぶと、HTTP APIの3.5倍のコストになる。キャッシュ・使用量プラン・APIキー管理などREST API固有の機能を使っていないなら、HTTP APIへの移行を検討する価値がある。
複数ステージのリクエスト数が合算されて請求される
API Gatewayでは1つのAPIにdev・stg・prodという複数のステージを作れる。便利な反面、全ステージのリクエスト数が合算されて1つの請求になる。「本番だけのコストのはず」という感覚とズレが生じやすい。
⚠️ よくある状況
本番:月500万リクエスト → 17.50USD(REST API)
開発・ステージング:合計月200万リクエスト → 7.00USD合計 24.50USD。本番だけのつもりで見ていると、2〜3割多く請求されていることに気づかないまま運用が続く。
加えて、開発中に負荷テストツール(k6・Locustなど)を使ったあと、ツールの停止や定期実行スクリプトの削除を忘れてしまうケースもある。リクエストが流れ続ける限りコストが積み上がるため、テスト後のクリーンアップをルール化しておくことが重要だ。
WebSocket APIは接続時間で課金される
WebSocket APIはREST・HTTPと異なり、 接続時間(分)とメッセージ数 の両方で課金される(0.29USD/百万接続分+1.00USD/百万メッセージ)。チャットや通知システムで長時間接続が多い場合、メッセージのやりとりが少なくても接続時間だけでコストが積み上がる。設計前に接続数×平均接続時間の試算をしておく。
Lambdaのタイムアウト値を長く設定しすぎている
Lambdaの最大実行時間(タイムアウト)はデフォルト3秒で、最大15分まで設定できる。「念のため長くしておく」という判断でタイムアウトを15分に設定している関数は、バグによる無限ループや外部APIの応答待ちが発生した場合に、タイムアウトするまでフル課金され続ける。
❌ よくある状況
外部APIを呼び出すLambdaのタイムアウトを15分に設定。外部APIが応答しなくなったとき、1回の実行で900秒分が課金された。512MBで900秒なら1回約0.0075。同時実行が100件あれば1回の障害で0USD.75、1日数百回呼ばれていれば気づかないうちに積み上がる。
SQSトリガーのBatchSizeが小さく、Lambda呼び出し回数が増えている
SQSをトリガーにしたLambdaは、BatchSize(1回の実行で取得するメッセージ数)の設定によってLambdaの呼び出し回数が変わる。デフォルトのBatchSize=1のまま使い続けると、メッセージ1件ごとにLambdaが1回起動するため、大量のメッセージを処理する場合に呼び出し回数が膨らむ。
⚠️ 設計フェーズで確認すべき
BatchSizeを大きくすれば1回のLambda実行で複数メッセージを処理できるため、呼び出し回数を減らせる。ただし1件でもエラーになるとバッチ全体がリトライされるため、べき等性の確保とエラーハンドリングの設計がセットで必要になる。
判断軸
- 月間リクエスト数が1,000万を超えてくる場合は、FargateやEC2とのコスト比較を設計フェーズで行う
- Lambdaのタイムアウトは「想定される最長処理時間+余裕」を上限に設定する。15分のままにしない
- SQSトリガーの
BatchSizeは処理の特性とエラーハンドリング設計をセットで検討する - Provisioned Concurrencyはつけたら終わりではなく、Application Auto Scalingと組み合わせて確保数を動的に管理する
- コールドスタートが気になる場合は、まずデプロイパッケージの軽量化・初期化コードの整理で改善できないか試す
- 2025年8月以降のINIT課金の影響は、CloudWatch Logs Insightsで Init Duration を確認して実態を把握する
4. データ分析基盤(S3 + Athena / Glue)
S3をデータレイクとして、AthenaやGlueで分析・ETLを行う構成は、運用が楽でスケーラブルだ。
反面、S3のデータ格納方法とAthenaのクエリ設計が、そのままコストに直結する構造になっている。
「使った分だけ払う」が思わぬ額になりやすい典型例だ。
パーティションなしのS3にAthenaでクエリを打ち続ける
Athenaの料金は スキャンしたデータ量に対して課金 される(5USD/TB)。パーティション設定のないテーブルに WHERE 句で絞り込みをかけても、Athenaの目線ではS3上の全データが対象になる。
❌ よくある状況
ログデータをフラット(日付構造なし)にS3へ格納。「先週分のデータだけ見たい」というクエリを実行するたびに全量スキャンが走る。データが3TBを超えたあたりで、1クエリあたり15USD前後のコストが発生していることに気づく。
対策は2つを組み合わせるのが基本だ。 パーティショニング(年/月/日などのプレフィックス構造でS3に格納する) と、 Parquet形式への変換(列指向フォーマット) 。
Parquetは必要な列だけを読み込む特性があるため、列を絞るクエリ前提であればスキャン量を最大で85〜95%削減できると言われている。
ただし「どの列を使うか」によって効果は変わるため、フルスキャンが避けられないクエリには限界もある。
GlueのDPUをデフォルトのまま使い続ける
Glueはジョブ実行時間とDPU(データ処理ユニット)数の積で課金される。デフォルトのDPU数は10で、小規模なETLでもこの設定で動かしているケースがある。
実測せずにデフォルトのまま運用しているジョブは、2〜4 DPUで十分なことが多い。また、短時間で終わるジョブでも課金最低単位(1分)が適用されるため、頻繁に起動する軽量ジョブはLambda+Pandas(またはDuckDB)で代替するのも選択肢だ。
S3バージョニングを有効にしたままライフサイクルを設定していない
S3のバージョニングは誤削除・上書き対策として有効な機能だが、有効化するだけではコスト管理が追いつかない。ファイルを「削除」しても旧バージョンはS3に残り続けるため、データが蓄積するほどストレージコストが増大する。
❌ よくある状況
ログファイルをS3に書き出し、定期的に削除するスクリプトを動かしている。しかしバージョニングが有効なため「削除」は削除マーカーの追加にすぎず、旧バージョンのデータは残り続ける。数ヶ月後にS3のコストが想定の3〜5倍になっていることに気づく。
ライフサイクルルールで「旧バージョンを30日後に削除」「不完全なマルチパートアップロードを7日後に削除」を設定しておくことで、バージョニングのコストを制御できる。バージョニングを有効にするなら、ライフサイクルルールはセットで設計する。
Glacierに移したデータを短期間で取り出す
S3 GlacierやGlacier Deep Archiveはストレージ単価が安いが、データ取り出しに時間とコストがかかる。「安いから全部Glacierに移す」という判断で、アクセス頻度が読めないデータを移行してしまうと、取り出しコストが移行によるコスト削減を上回るケースがある。
⚠️ 設計フェーズで確認すべき
Glacier Flexible Retrievalには最低保存期間(90日)があり、それ以前に削除・取り出しをすると早期削除料金が発生する。Deep Archiveは180日。取り出し頻度が月1回以上あるデータはGlacierではなくIntelligent-Tieringの方がトータルで安くなることが多い。
判断軸
- Athenaを使うなら、S3の格納設計(パーティション構造)はセットで設計する。後から変更するコストが高い
- データが数百GB以上になるならParquet変換は早めに対応する。変換コストは後で回収できる
- S3バージョニングを有効にするならライフサイクルルールをセットで設定する
- アクセス頻度が不明なデータはGlacierより先にIntelligent-Tieringを検討する
- GlueのDPU数は実測してから調整する。デフォルト(10 DPU)のまま本番投入しない
- 定期バッチが不要な軽量ETLはGlueを使わずにLambda+Pandas(またはDuckDB)も検討する
5. CDN構成(CloudFront + S3 / ALB)
CloudFrontはエッジキャッシュでオリジンへのリクエストを減らし、レイテンシとコストを同時に改善する。ただし「CloudFrontを入れる=コストが下がる」ではない。キャッシュが機能していない構成では、オリジンへの転送コストに加えてCloudFrontのコストまで発生するという逆効果になる。
キャッシュヒット率が低いまま放置されている
動的コンテンツの比率が高い、またはCache-Controlヘッダーが設定されていない場合、CloudFrontはほぼすべてのリクエストをオリジンに流す。この状態ではオリジンへの転送コストが減らないまま、CloudFrontのデータ転送コストだけが追加される。
⚠️ まず確認すべき指標
CloudWatchでキャッシュヒット率を確認する。静的コンテンツが中心なら90%以上が目安で、それを下回る場合はキャッシュポリシーやCache-Controlヘッダーの見直しが必要だ。一方で、APIレスポンスなど動的コンテンツが主体の構成では、そもそも高いキャッシュヒット率は期待できない。その場合は「CDNを入れるべきか」自体を問い直す価値がある。
オリジンとのデータ転送コストを見落としている
CloudFrontとALBが同一リージョンにある場合、CloudFront↔ALB間のデータ転送は無料だ。ただしALBからEC2(バックエンド)へのトラフィックに伴うデータ転送コストは発生するため、見落としがちだ。また、CloudFrontとオリジンが異なるリージョンにある場合はリージョン間転送コストも加算される。
✅ 設計のポイント
S3をオリジンにする場合、CloudFrontとS3が同一リージョンにあればS3側のデータ転送コストは発生しない。ALBをオリジンにする場合も同一リージョンであればCloudFront↔ALB間の転送は無料だが、ALBをプライベートサブネットに置きCloudFront VPC Origins(2024年11月〜)を使うとALBへのパブリックアクセスを不要にできる。静的アセットはS3オリジン、動的コンテンツはALBオリジンに分けるOrigin Groupの設計も、コストと管理のバランスを取りやすい。
WAFのルール数とリクエスト評価コストを見落としている
AWS WAFをCloudFrontにアタッチすることでDDoS対策や不正リクエストのブロックができる。ただしWAFはWebACLの月額料金(5USD/月)に加え、ルール数(1USD/ルール/月)とリクエスト評価数(0.60USD/100万リクエスト)でも課金される。マネージドルールグループを複数追加していくとルール料金が積み上がり、高トラフィックなサイトではリクエスト評価コストも無視できなくなる。
ルールによって料金の差も大きい。通常のマネージドルールは1USD/月だが、Bot Controlは月額10USD+1USD/百万リクエスト、Fraud Control(ATPなど)はさらに高い。「とりあえず全部有効」にしているとこの差が積み上がる。
⚠️ 設計フェーズで確認すべき
マネージドルールグループを「とりあえず全部有効」にしているケースがある。実際に必要なルールに絞ることでルール料金を抑えられる。また、CloudFrontのキャッシュヒット率が高い構成ではオリジンへのリクエストが減るためWAFの評価回数も下がる。キャッシュ設計とWAFコストは連動して考える。
✅ ルール評価順とScope-down Statementの活用
WAFはルールを優先度順に評価し、BlockまたはAllowにマッチした時点で後続のルールを評価しない。これを利用して、IPブロックリストやGeo制限のような「安くて大量に弾ける」ルールを上位に置くと、高コストなBot Controlなどの評価対象リクエスト数を減らせる。
優先度1:IPブロックリスト(1USD/月)→ 悪意あるIPをここで弾く 優先度2:Geo制限(1USD/月) → 対象外リージョンをここで弾く 優先度3:Bot Control(10USD/月+従量)→ ここまで残ったリクエストだけ評価さらにBot ControlやFraud Protectionには「Scope-down Statement」を設定することで、評価対象を特定のパス(
/loginや/api/*など)に限定できる。対象外のリクエストは評価されないため、その分の課金も発生しない。
判断軸
- CloudFront導入前に「キャッシュできるコンテンツの比率」を見積もる。動的コンテンツがほぼすべてなら効果は薄い
- キャッシュヒット率は導入後も継続的に監視する。低い場合はビヘイビア設定とCache-Controlヘッダーを見直す
- Price Class(全エッジロケーション vs 主要リージョンのみ)の設定でデータ転送コストを絞り込める
- WAFを使う場合はルール料金の高低を意識し、安いルールを上位に、高コストなBot Controlなどは必要なパスにScope-downして適用する
6. マルチアカウント構成(AWS Organizations)
複数のAWSアカウントをOrganizationsで管理するマルチアカウント構成は、セキュリティ境界とコスト管理の両面で有効だ。
ただし共有リソースの設計を誤ると、アカウントが増えるほどコストが重複して積み上がる構造になる。
各アカウントでNAT Gatewayを重複して持つ
各アカウントに独立したVPCを持たせる構成では、アカウントごとにNAT Gatewayを配置することになる。
NAT Gatewayは稼働時間課金(0USD.062/時間/台、ap-northeast-1〈東京〉)とデータ処理量課金の両方が発生するため、アカウント数が増えると固定コストが大きくなる。
⚠️ 試算例(本番環境のみ、2AZ構成)
10アカウント × 2AZ = 20台のNAT Gatewayが常時稼働している場合、稼働コストだけで月906USD程度(0.062USD × 730時間 × 20台)の固定費になる。これはデータ処理コストを含まない下限の数字だ。
Transit Gateway+Centralized Egress VPCを使ってNAT Gatewayを集約する設計(Centralizedアーキテクチャ)に切り替えることで、NAT Gateway台数を大幅に削減できる。
📝 2025年11月のアップデート(Regional NAT Gateway)について
AWSは2025年11月にRegional NAT Gatewayをリリースした。従来は「AZごとに1台」が必要だったNAT Gatewayを、1つのリソースでVPC全体のAZをカバーできるようになった。運用の簡素化や設定ミスの防止には効果的だ。ただし課金体系は「使用しているAZ数 × 0.062USD/時間(東京リージョン)」で変わらないため、NAT Gatewayの総数を削減するにはCentralized Egress構成と組み合わせる必要がある。「Regional NAT Gatewayにすればコストが下がる」という誤解には注意したい。
ログ集約の設計を後回しにしている
OrganizationsでのCloudTrail、Config、SecurityHub、VPC Flow Logsは全アカウントに自動適用されやすい。ログの保持期間・格納先・ログレベルを設計しないまま運用に入ると、不要なログが蓄積してS3コストが増大する。特にVPC Flow LogsをCloudWatch Logsに出力しているケースは、S3直接出力に比べてコストが高くなりやすい。
✅ 設計のポイント
ログはS3専用バケット(ログアーカイブアカウント)に集約し、アクセス頻度に応じてIntelligent-TieringまたはGlacier Instant Retrievalへのライフサイクル移行を設定する。VPC Flow LogsはS3直接出力にしてCloudWatch Logsを経由しない構成にする。
検証用アカウントのリソースを放置している
マルチアカウント構成では、検証・PoC用に作成したアカウントのリソースが長期間放置されるケースが多い。EC2インスタンスを停止しても、EIP(Elastic IP)・NAT Gateway・RDSインスタンス・未アタッチのEBSは課金され続ける。アカウントが増えるほどこのような放置リソースが散在しやすい。
❌ よくある状況
PoC完了後にEC2を停止して「終わった」認識になっている。しかしEIPは未割り当て状態でも課金(0USD.005/時間)、NAT Gatewayも削除しない限り時間課金が続く。気づいたときには数ヶ月分の不要なコストが積み上がっている。
CloudTrailをアカウントごとに個別有効化している
CloudTrailはデフォルトでアカウントごとに独立して設定できるが、Organizations全体をカバーする「組織のトレイル」を使えばすべてのアカウントのログを1ヶ所に集約できる。アカウントごとに個別トレイルを有効化している場合、同じAPIイベントが複数のS3バケットに書き込まれてストレージコストが重複する。
✅ 設計のポイント
Organizations全体のCloudTrailトレイルを管理アカウントで1つ作成し、全メンバーアカウントのログを集約する。個別アカウントのトレイルは無効化することで重複コストを排除できる。証跡の有効化・無効化はSCPで制御しておくと管理が楽になる。
判断軸
- アカウント数が5を超えてきたら、Centralized Egress構成への移行コストを試算する
- CloudTrailはOrganizationsトレイルに集約し、アカウントごとの個別トレイルを無効化する
- 検証用アカウントのリソースはIaCで管理し、PoC終了後は自動削除することをルール化する
- Cost Allocation TagsをSCP経由で強制する設計にしておくと、後のコスト分析が格段に楽になる
まとめ:設計フェーズで問うべきこと
| 構成 | コストが膨らむ設計判断 | 設計時に問うべきこと |
|---|---|---|
| Web 3層(ALB+EC2+RDS) | インスタンス固定・Multi-AZの一律適用・EBSの過大プロビジョニング・ALBの消し忘れ | スケーリングを前提にした設計になっているか? |
| ECS Fargate | タスクサイズ過剰・NAT経由のECR pull・パブリックIP自動アサイン・ステージングの最小タスク数 | VPCエンドポイントとプライベートサブネット構成を設計に含めているか? |
| API GW + Lambda | 高頻度でのコスト逆転・Provisioned Concurrencyの固定確保・タイムアウト過長・SQS BatchSize不足 | 想定リクエスト数でFargateと比較したか? |
| S3 + Athena/Glue | パーティションなしフルスキャン・DPU過剰・バージョニングのライフサイクル未設定・Glacierの早期取り出し | S3の格納構造とライフサイクルをAthenaとセットで設計したか? |
| CloudFront | キャッシュバイパス常態化・リージョン転送コスト・WAFルール過多 | キャッシュヒット率を導入前に見積もったか? |
| Organizations | NAT Gatewayの重複・ログ集約の設計不足・放置リソース・CloudTrailの重複 | 共有リソースをどのアカウントに集約するか決めているか? |
このように、 コストの問題は運用フェーズで突然現れるのではなく、設計フェーズの判断として最初から潜在している ということだ。後から気づいてSavings PlanやRIを購入しても、それは「すでに決まった構成を少し安くする」手段に過ぎない。あとから設計そのものを変えるのは大きな負担になる。
コスト効率のよい設計とは、最も安い選択をし続けることではない。ワークロードの特性と、各サービスの課金モデルがどう噛み合うかを理解したうえで、可用性・運用負荷・コストのトレードオフを意識的に選択すること だ。「なぜその構成にしたか」を設計レビューで説明できる状態が、長期的なコスト管理の出発点になる。
次の記事(第二部)
コスト・オブザーバビリティ — 運用フェーズのコスト管理設計
設計だけでは完結しない。異常に気づき、原因を追跡し、継続的に改善するための仕組みを最初から組み込む。タグ戦略・Budgetアラート・Cost Anomaly Detection・構成別メトリクスを解説する。