はじめに
過去に個人開発として、SageMakerでモデルを学習させていたときに、気づいたら$20ほど課金されていたことがあります。
インスタンスを立てたまま作業から離れてしまい、放置している間もインスタンス課金が発生し続けていた、というよくあるパターンです。被害額としては大きくありませんでしたが、想定していないコストが急にかかってしまうという感覚は、それ以降の個人開発でも常に心に引っかかっていました。
最近はBedrockをはじめとした生成AIサービスを組み込んだアプリ開発が、個人開発でもかなり身近になっています。ただこれは裏を返すと、コストの見通しがどんどん立てにくくなっているということでもあります。特にBedrockでAgentを複数作って役割分担させ、精度を上げようとすると、呼び出し回数やトークン量が想定以上に膨らみ、雪だるま式にコストが積み上がっていくことがあります。
「気づいたら数万円請求が来ていた」 は、個人開発において怖いシナリオの一つです。だからこそ、今回はAI関連の機能を作る前に、最初にきちんと閾値を設けて「超えたら止める」仕組みを作ることにしました。
この記事では、その仕組みを実現する設定手順と注意点をまとめます。AIサービスの開発をきっかけに作った仕組みですが、内容自体はAIを使わない個人開発でも共通して役立つはずです。
まず、AWSでコストを管理する手段にはどんな選択肢があるのか整理してみます。
コスト管理サービスの全体像
AWSにはコストに関わるサービスがいくつかあり、それぞれ役割が違います。今回検討時に整理した内容を共有します。
| サービス | 主な役割 | 得意なこと |
|---|---|---|
| AWS Budgets | 予算設定・閾値通知・アクション実行 | 「いくらまでに抑えたい」という予算ベースでの管理、超過時のブロック |
| Cost Explorer | コストの可視化・分析 | 過去のコスト推移やサービス別内訳の分析 |
| Cost Anomaly Detection | 異常検知 | 普段と違うコストの急増を機械学習で検知して通知 |
| Service Quotas | サービスごとの上限管理 | API呼び出し数やリソース数そのものの上限設定 |
個人開発でBedrockやSageMakerを使う程度の規模であれば、
- 「予算という絶対額の上限を決めて、それを超えたら止める」Budgets
- 補助的に、日々の推移を確認するCost Explorer
の組み合わせで十分だと判断しました。Cost Anomaly Detectionは魅力的な機能ですが、あくまで「検知して通知」までで自動ブロックはしてくれません。今回のように「止めるところまでやりたい」という目的に対して単体では実現できません。まずはBudgetsで下限のセーフティネットを作っておいて、余裕が出てきたら異常検知系を足していく、というのが個人開発に合った進め方だと思っています。
AWS Budgetsとは
AWS Budgetsは、AWSの利用コストに対して予算を設定し、閾値を超えた(または超えそうな)タイミングで通知やアクションを実行できるサービスです。
- 予算額に対する実績コストでの通知
- 予算額に対する予測コストでの通知(このままいくと超えそうというタイミングで検知)
- 通知だけでなく、IAMポリシーの適用やSCPの適用といったアクションの自動実行
単なるアラートサービスだと思われがちですが、「超えたら実際に止める」ところまでカバーできるのが個人開発する上では一番の助かりポイントです。
今回のインフラ構成(簡単に)
今回コスト制御の対象にしたのは、開発中の食材管理アプリの中で、AIを使っている部分です。
このアプリでは、レシートから食材の自動登録と、食材を使ったレシピを提案する、という機能を作っています。この「レシート画像から食材を読み取る」「食材からレシピを考える」という部分に、Amazon Bedrockを使っています。
構成としてはシンプルで、
- アプリからのリクエストを API Gateway → Lambda が受ける
- Lambdaが Bedrock を呼び出し、画像解析・レシピ生成の結果を返す
という流れです。この「AIを呼び出す部分」こそが、呼び出し回数や画像サイズ次第でコストが伸びやすいポイントです。そのため今回は、コストが予算を超えた場合に Lambdaの実行そのものをIAMポリシーで止める ようにしました。
設定手順
1. 予算の作成
「請求とコスト管理」→「予算」から、以下の内容で予算を作成します。
- 予算の設定:カスタマイズ(アドバンスト)
- 予算タイプ:コスト予算
- 予算名:管理しやすい名前を自由に設定
- 期間:月
- 予算更新タイプ:定期予算
- 予算設定方法:固定
- 予算額:$10
- 予算の範囲:すべてのAWSサービス
- コストの集計基準:非ブレンドコスト
これからAIサービスを組み込んだ検証を始める前提で、最初は低めの $10 に設定しています。「これ以上かかると困る・おかしい」というラインを最初に引いておくのが目的です。
2. アラートの設定(3段階)
| アラート | しきい値 | トリガー |
|---|---|---|
| Alert #1 | 予算額の85% | 実際のコスト |
| Alert #2 | 予算額の100% | 予測コスト |
| Alert #3 | 予算額の100% | 実際のコスト |
アラートの受信先には、通知を受け取りたいメールアドレスを登録してください。
予測コストによるアラート(Alert #2)を実績コストのアラートの間に挟むことで、実績が閾値に達するより前に通知で気づけるようにしています。
3. IAMロールでのアクション紐付け
「アクションをアタッチ」のステップで、Alert #3(実際のコスト100%)に対して、通知だけでなく実際に実行を止めるアクションを紐付けます。
BudgetsがアクションとしてIAMポリシーを付け外しできるようにするには、事前にIAMロール・ポリシーをいくつか用意しておく必要があります。
① IAMポリシーのアタッチ/デタッチを許可するポリシーを作成
Budgetsが自動で付け外しできるようにするための権限ポリシーです。ポリシー名はBudgetsIAMPolicyAttachAccessとしました。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"iam:AttachGroupPolicy",
"iam:AttachRolePolicy",
"iam:AttachUserPolicy",
"iam:DetachGroupPolicy",
"iam:DetachRolePolicy",
"iam:DetachUserPolicy"
],
"Resource": "*"
}
]
}
② Budgets用のIAMロールを作成
Budgetsサービスが予算超過時のアクション(今回で言えばDenyポリシーのアタッチ)を実行するためのロールです。ロール名はAWSBudgetsActionsRoleとしました。信頼するエンティティにはBudgetsサービスを指定し、aws:SourceAccount条件で自分のアカウントからの呼び出しに限定します。
-
信頼できるエンティティタイプ:
カスタム信頼ポリシー
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "budgets.amazonaws.com"
},
"Action": "sts:AssumeRole",
"Condition": {
"StringEquals": {
"aws:SourceAccount": "自分のアカウントID"
}
}
}
]
}
-
許可ポリシー:以下の2つのポリシーをアタッチ
-
AWSBudgetsActionsWithAWSResourceControlAccess
(AWS管理ポリシー、Budgets機能を使うための基本的な権限セット) - ①で作成した
BudgetsIAMPolicyAttachAccess
-
③ Denyポリシーを作成
予算超過時に、Lambdaの実行を拒否する権限を持つポリシーを作成します。ポリシー名はDeny-FridgeApp-CostLimitとしました。(自身の環境に合わせて適切に設定してください)
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Deny",
"Action": "lambda:InvokeFunction",
"Resource": "arn:aws:lambda:ap-northeast-1:xxxxxxxxxxxx:function:fridge-app-*"
}
]
}
- Action — 止めたいアクションを絞る。今回はLambdaの実行を対象にしている
-
Resource — 対象を絞る。
fridge-app-*のように対象のLambda関数だけに限定することで、「コストが伸びているAIの部分だけを止めて、他の機能は継続」という設計にしている
④ Budgetsのアクション設定
Alert #3のアクション設定画面で以下を指定します。
-
IAMロール:
AWSBudgetsActionsRole - アクションタイプ:IAM Policy
-
適用する既存ポリシー:③で作成したDenyポリシー(
Deny-FridgeApp-CostLimit) - 適用対象:実行を拒否したいリソースのロール(今回はBedrockを呼び出しているLambdaのロール)
- 自動実行:はい
- アクション実行時のアラートの受け取り方法:このしきい値を定義したときと同じアラート設定を使用
閾値を超えるとどうなるか
流れとしては、
- 予算超過を検知すると、Budgetsが自動でこのDenyポリシーをLambdaのロールにアタッチする
- Lambdaが処理を実行できなくなり、コストの発生が止まる
という仕組みです。実際に閾値を超えると、このようなメールが届きます。
(画像は閾値を下げて引っ掛かるようにしたものです。)

Lambdaを実行しようとすると、権限エラーで弾かれるようになります。
本番運用における注意点
ここまでの設定はあくまで個人の検証環境を想定したものです。このまま本番サービスに適用すると、想定外のタイミングでサービスが丸ごと停止してしまうリスクがあります。実際にサービスを提供する場合は、以下のような工夫を検討する必要があります。
- 段階的なアクション:いきなり停止ではなく、まず新規リクエストの受付だけ制限する、無料枠のユーザーだけ制限するなど、影響範囲を段階的に広げる
- 自動実行にしない選択肢:自動実行を「いいえ」にして、アラートを受けた上で人間が最終判断してから実行する運用にする
- 環境を分ける:本番用と検証用でAWSアカウント(またはリソース)を分離し、検証環境にだけ厳しめの自動ブロックを設定する
- 監視との併用:Cost Anomaly Detectionなどで異常な伸び方をいち早く検知し、閾値に達する前に手動対応できるようにしておく
そして他にも重要な注意点があります。それは、一度アタッチされたDenyポリシーは、Budgetsが自動で外してくれるわけではないということです。
翌月になって予算がリセットされても、ポリシー自体は手動で外すまでロールに付いたままとなります。つまり「先月は予算超過で止まったが、今月もLambdaが動かない」という事態が起こり得ます。私自身はまだこのパターンにハマった経験はありませんが、仕組み上確実に起こり得ることなので、運用に組み込む際は必ず頭に入れておいてください。
また、検知そのものにタイムラグがあるという点も見落としがちです。コストが実際に発生してから請求データに反映されるまで最大24時間、さらにBudgets自体の更新は1日に最大3回(前回の更新からおおよそ8〜12時間後)というペースのため、実際に予算を超えてからアクションが発動するまで、丸1日近くかかることもあり得ます。
まとめ
- AWS Budgetsは通知だけでなく、IAMポリシーの自動適用による「止める」アクションまで実現できる
- 検証環境では自動ブロックが有効だが、本番環境では止める対象やタイミングを慎重に設計する必要がある
- アタッチされたDenyポリシーは自動では外れないので、解除作業も含めて運用を考える必要がある
最初は「アラートだけ設定しておけばいいだろう」くらいに考えていました。しかし個人開発の場合、メールなど通知に気づかず放置してしまうなどのリスクもありますので、こうしたコストのセーフティネットを用意しておくことをおすすめします。
この記事が役に立ったら、いいね・フォローしてもらえると次の記事のモチベーションになります。次回はAI駆動開発(Claude Code)まわりの記事を予定しています。