「先月のCloudWatch Logsの請求が想定の3倍になっていた」「ログを溜め込み続けたら、いつの間にかEC2より高い料金になっていた」——AWSをある程度運用していると、こんな相談を受けることが増えてきます。オンプレ時代はディスクが安く、ログは「とりあえず全部残す」が標準でした。ところがクラウドの従量課金では、その感覚のままだと請求書を見て青ざめることになります。
この記事では、Amazon CloudWatch Logsのコスト構造と削減手段について、オンプレ経験者にもわかりやすく解説します。データ取込(Ingestion)料金、ストレージ保管料金、データ転送料金の三本柱と、それぞれを抑えるための実践テクニックを、設計段階から運用フェーズまで通して整理します。

なぜCloudWatch Logsの料金は膨らみやすいのか?
オンプレのログ管理では、rsyslogでファイルに書き出し、logrotateで圧縮し、古いものを月次でテープに退避する——というのが定石でした。ストレージは内蔵HDDか共有ストレージで、追加コストは「ディスク増設のたびに発生する固定費」として認識されます。
一方、CloudWatch Logsは「ログを送り込んだバイト数」「保管しているバイト数」「他リージョンへ転送したバイト数」のそれぞれに従量課金が発生します。特にIngestion(取込)料金は東京リージョンで$0.76/GB(2026年5月時点)と決して安くなく、アプリのDEBUGログを全部送り続けると、想定の2~5倍の請求が来ることはざらにあります。
料金が膨らみやすい構造的な理由は以下のとおりです。
・取込が高い: ストレージより取込のほうが約25倍高単価。「とりあえず全部送る」がそのままコスト爆発に直結する
・保管期限のデフォルトが「無期限」: ロググループ作成時に保持期間を指定しないと、削除しない限り永久に課金される
・VPC Flow LogsやCloudTrailが地味に重い: 通信量の多いVPCではFlow Logsだけで月数百GB、認証密度の高いアカウントではCloudTrailデータイベントが日単位GB級になる
・クロスアカウント・クロスリージョン転送: マルチアカウント集約構成では、ログ転送料金も加算される
オンプレ感覚で「ログは全部残しておこう」と判断すると、CloudWatch Logsだけで月数万~数十万円の請求書が届きます。設計段階で「何をどのくらいの粒度で、どこに、何日間置くか」を決めておくことが、コスト最適化の前提になります。
CloudWatch Logs料金体系の基本
削減策に入る前に、料金の三本柱を整理します。東京リージョン(ap-northeast-1)の代表的な単価は以下のとおりです(2026年5月時点)。
| 項目 | 単価 | 説明 |
|---|---|---|
| 標準クラス 取込(Ingestion) | $0.76/GB | ログをCloudWatch Logsに取り込んだバイト数に対して課金 |
| Infrequent Access クラス 取込 | $0.38/GB | 低頻度アクセス用クラス。検索とアラート機能は制限あり |
| ストレージ保管 | $0.033/GB/月 | ログを保管している期間中、圧縮後サイズに対して課金 |
| データ転送(リージョン間) | $0.09/GB | クロスリージョンでログを集約する場合に発生 |
| Logs Insights クエリ | $0.0076/GB | スキャンしたバイト数に対して課金。長期間検索は高額化しやすい |
注目すべきは、取込料金とストレージ料金の比率です。取込$0.76と保管$0.033では実に約23倍の差があります。つまり「ログ保管期間を1か月から1週間に短縮する」よりも、「取込量自体を半減させる」ほうが、削減インパクトは何倍も大きいということです。コスト削減の優先順位は、まず取込量、次に保管期間、最後にクエリと転送という順番で考えるのが鉄則です。
削減策1: ログ取込量そのものを減らす
最も効果が大きいのが、CloudWatch Logsに送る前段階での削減です。具体的な手段を、影響度の大きい順に並べます。
1. ログレベルの本番運用設定
開発時のままDEBUGレベルでアプリを動かしているケースは、想像以上に多く見かけます。本番ではINFO以上、できればWARN以上に絞り込みましょう。Springアプリの例で書くと以下のとおりです。
# Spring Boot application.yml(本番プロファイル) logging: level: root: WARN com.example.app: INFO org.hibernate.SQL: WARN org.springframework.web: WARN
DEBUGからINFOに上げただけで、取込量が80%以上減るケースも珍しくありません。アクセスログを全リクエスト出力している場合は、ヘルスチェック系(/health、/ping)を除外するだけでも数十%削減できます。
2. VPC Flow Logsの選別
VPC Flow Logsはセキュリティ運用に必須ですが、全VPC・全インターフェイスをCloudWatch Logsに送ると、すぐにGB級になります。コスト削減の鉄則は2つです。
・送信先をS3にする: CloudWatch LogsではなくS3に直接配信すれば、取込料金がかからず保管料金もS3の$0.025/GBで済む
・aggregation_intervalを10分に: デフォルトは1分単位だが、10分集約に変更するとログ量を大幅削減できる
・filterで絞り込む: REJECTのみ記録する設定にすれば、許可されたトラフィック分のログを丸ごとカットできる
3. CloudTrailデータイベントの精査
CloudTrailの管理イベントは無料ですが、データイベント(S3オブジェクトレベル、Lambda呼び出しなど)は$2.00/100万イベントで課金されます。特にS3データイベントは、アクセス頻度の高いバケットを全部対象にすると爆発的に増えます。
・本番監査が必要なバケットのみ対象指定する
・読み取り(Get)と書き込み(Put)を必要に応じて分ける
・データイベントの宛先はCloudWatch LogsではなくS3を選び、Athenaで分析する
4. アプリ側のサンプリング
大量リクエストを処理するAPIでは、全リクエストのログを残す必要はありません。エラーは100%、成功は10%サンプリング、といった戦略を取ります。AWS Lambdaの例だと以下のような実装になります。
# Python(Lambda)でのサンプリング例 import random import logging logger = logging.getLogger() logger.setLevel(logging.INFO) def lambda_handler(event, context): try: result = process(event) # 成功ログは10%だけ記録 if random.random() < 0.1: logger.info(f"Success: {result['id']}") return result except Exception as e: # エラーは100%記録 logger.error(f"Failed: {str(e)}", exc_info=True) raise
削減策2: ログクラスを使い分ける
2023年末に追加されたCloudWatch Logs Infrequent Access(IA)クラスは、「保管はしたいが、ほぼ検索しないログ」を半額の取込料金で受け入れるオプションです。標準クラスとの違いを整理します。
| 項目 | 標準クラス | Infrequent Access |
|---|---|---|
| 取込料金 | $0.76/GB | $0.38/GB(約50%減) |
| ストレージ料金 | $0.033/GB/月 | $0.033/GB/月(同額) |
| Logs Insights検索 | ○ | ○(同額) |
| メトリクスフィルター | ○ | × |
| Subscriptionフィルター | ○ | × |
| ライブテール | ○ | × |
使い分けの判断基準はシンプルで、「リアルタイム検知やメトリクス変換が必要か?」です。必要ならば標準、不要ならIAを選びます。たとえば以下のように分類するとわかりやすいでしょう。
・標準クラス: アプリケーションログ(エラー監視)、CloudTrail(不正検知)、認証ログ
・Infrequent Access: アクセスログのアーカイブ、長期保管用の監査ログ、VPC Flow Logsの一部
ロググループ単位でクラスを指定するため、設計時点で「このログは何に使うか」を整理しておくと運用が楽になります。
削減策3: 保管期間を必ず設定する
ロググループのデフォルト保管期間は「無期限」です。これがコスト膨張の隠れた元凶になることが多いので、ロググループを作成したら必ず保管期間を設定する運用にしましょう。
AWS CLIでの一括設定例(東京リージョンの全ロググループを30日に変更)は以下のとおりです。
# AWS CLI: 全ロググループの保管期間を30日に揃える aws logs describe-log-groups --region ap-northeast-1 \ --query 'logGroups[?retentionInDays==`null`].logGroupName' \ --output text | tr '\t' '\n' | while read lg; do aws logs put-retention-policy \ --log-group-name "$lg" \ --retention-in-days 30 \ --region ap-northeast-1 done
業種別の推奨保管期間の目安は以下です。
・アプリログ(Web/API): 14~30日(エラー追跡用途)
・アクセスログ: 90日(不正アクセス追跡)
・VPC Flow Logs: 90日(CloudWatchで保持する場合)
・CloudTrail監査ログ: 7年(長期はS3+Glacier Deep Archiveが現実的)
・セキュリティ系(GuardDuty/Security Hub): 90日~1年
長期保管が必要なログは、CloudWatch Logsに置きっぱなしにせず、S3にエクスポートしてS3 Glacier Deep Archive($0.0017/GB/月)に階層化するのが王道です。CloudWatch Logsで90日保管 → 自動でS3にエクスポート → 1年経過後にGlacier Deep Archiveに移行、という3段構成にすると、長期保管コストを1/20以下に圧縮できます。
削減策4: Logs Insightsクエリのコスト管理
Logs Insightsは強力な検索エンジンですが、スキャンしたバイト数に対して課金されるため、長期間・大容量を雑に検索するとクエリ1本で数千円かかることがあります。コスト削減のコツは以下のとおりです。
・時間範囲を狭める: 「過去24時間」ではなく「過去1時間」で先に試す
・ロググループを絞る: 全ロググループ横断検索ではなく、関連グループだけを対象に
・フィルターを早く適用する: クエリ序盤に filter を置き、後段のスキャン量を減らす
・parseは最小限に: parse や stats はスキャン後の処理だが、その前に filter で行数を絞っておく
例として、エラー件数を集計する効率的なクエリは以下のようになります。
# Logs Insights クエリ例(効率重視) fields @timestamp, @message | filter @message like /ERROR/ | filter level = "ERROR" | stats count() as err_count by bin(5m) | sort @timestamp desc | limit 100
応用Tips: 自動削減パイプラインの構築
運用が定着してくると、「ログ取込量が増えたら自動でアラート」「保管期間未設定のロググループを自動で30日に変更」といった自動化が効きます。
取込量の月次モニタリング
CloudWatchメトリクスの IncomingBytes をロググループ別に集計し、前月比で200%増になったロググループをSNS通知する仕組みを組むと、暴走を早期発見できます。AWS Cost Explorerでも「CloudWatch」サービスの日次推移を見ておくと、急増の検知が容易です。
保管期間自動設定
EventBridgeで CreateLogGroup APIをトリガーに、Lambdaで自動的に保管期間30日を設定するルールを組むと、設定漏れが構造的に防げます。
# Lambda: 新規ロググループに30日保管を自動適用(Python) import boto3 logs = boto3.client('logs') def lambda_handler(event, context): log_group_name = event['detail']['requestParameters']['logGroupName'] logs.put_retention_policy( logGroupName=log_group_name, retentionInDays=30 ) return {'status': 'applied', 'logGroup': log_group_name}
S3エクスポートの定期実行
90日以上保管が必要なログは、月次でS3にエクスポートしてCloudWatch Logsからは削除します。CreateExportTask APIをStep Functionsで定期実行すれば、運用負荷ゼロで階層化できます。長期監査ログはこの方式で月額数百円~数千円のコストに収まります。
よくあるトラブルと対処法
請求書を見たらCloudWatchが想定の10倍だった
原因の8割は「DEBUGログが本番で動いている」「無限ループでログを吐き続けている」「全リクエストにスタックトレースを出している」のいずれかです。まずはCost Explorerの Usage Type で APN1-DataProcessing-Bytes(取込)の推移を確認し、急増した日からアプリのデプロイ履歴を遡ります。Logs InsightsでロググループごとのIncomingBytesを集計すれば犯人グループが特定できます。
VPC Flow LogsをCloudWatchに送ったらストレージ料金が高騰
大規模VPCのFlow LogsはCloudWatch Logsに送らず、最初からS3に配信するのが定石です。既にCloudWatchに送ってしまった場合は、Flow Logs設定を作り直してS3に切り替え、CloudWatch側の古いログは保管期間を短く設定して自然消化させます。
Logs Insightsクエリでタイムアウトが頻発する
長期間×大容量のスキャンが原因です。時間範囲を狭めるか、 filter を最前段に置いて初期スキャン量を減らすことで解決します。それでも遅い場合は、S3にエクスポートしてAthenaで検索する方式に切り替えると、料金も性能も改善することが多いです。
ロググループ数が数千個に膨れ上がって管理しきれない
Lambdaが自動生成する /aws/lambda/関数名 形式のロググループや、ECSタスクごとに作られるロググループが原因のことが多いです。命名規則で /app/サービス名/環境 のように階層化し、Resource Groupsでまとめて管理する設計に変えると、保管期間の一括変更やコスト集計が楽になります。
本記事のまとめ
CloudWatch Logsのコスト削減は、「取込量を減らす → ログクラスを使い分ける → 保管期間を必ず設定する → 長期保管はS3階層化に逃がす」の順で取り組むのが最短ルートです。特に取込料金は保管料金の23倍と圧倒的に高単価なので、アプリのログレベル見直しとVPC Flow Logsの送信先変更だけで、請求の半分を削れることもあります。
オンプレ時代の「ログは全部残す」発想から、「目的別に粒度・期間・置き場所を分ける」発想に切り替えるのが、クラウドネイティブな運用設計の第一歩です。
Linuxサーバー側でのログ運用(rsyslog、logrotate、journald)の基礎については、姉妹サイトLinuxMaster.JPで詳しく解説しています。クラウドにログを送り出す前段の設計を見直すと、CloudWatch側のコストはさらに圧縮できます。
CloudWatch Logsの請求書、見直す勇気はありますか?
ログのコスト削減は、設計と運用の小さな見直しの積み重ねで、月額数万円~数十万円のインパクトを生みます。
オンプレの経験を活かしながら、現場で使えるクラウドスキルを体系的に身につけたい方へ、メルマガで実践的なクラウド活用ノウハウをお届けしています。

コメント