個人 AWS で毎月 4 万円溶かしていたので大掃除した
個人アカウントの AWS で、月 ¥38,000 くらい払っていた状態が 2 ヶ月続いていました。
プロモーションクレジットが適用されていたため利用額に気付かず、残高がなくなって実費請求が来てから確認しました。
2 日かけて大掃除した結果、月 ¥2,200 まで下がった (94% 減) ので、何にお金が消えていたのかと、どう削ったのかを記録します。
クレジットの枯渇で気付く
去年の re:Invent でもらった数百ドル分の AWS クレジットが残っていて、実費はほぼゼロで運用できていました。
クレジット残高は AWS Console の Billing → Credits からしか見えません。
CLI にも list-credits のような公式 API はないため、cron で監視することもできず、気付いたら残高がゼロになっていました。
適用状況を後追いで見るには、Cost Explorer の UnblendedCost と NetUnblendedCost の差分を取ります。
aws ce get-cost-and-usage \
--time-period Start=2026-06-01,End=2026-09-01 \
--granularity MONTHLY \
--metrics UnblendedCost NetUnblendedCost
UnblendedCost - NetUnblendedCost が実際に適用されたクレジット額です。
今回の場合、2026 年 6 月まではこの差分が月 ¥30,000 前後あり、7 月に入ってから急にゼロになりました。
大掃除の対象は主に次の 4 つ
1. 休止中の個人サービスの残存リソース (月 ¥25,000 以上)
運用していた「完全受注生産の衣服を扱う LINE ミニアプリ」を一時休止した際に、CloudFormation スタック一式が残ったままでした。
サービスとしては停止していても、内部で動いていた RDS インスタンス 2 系統 (dev / prod)、それぞれに紐付いた NAT Gateway、CloudFront ディストリビューション、Lambda、複数の EIP、Serverless Framework が作った serverlessdeploymentbuck-* の S3 バケット、CloudWatch Logs、周辺のサブシステム用に立てていた EC2 まで含めて課金され続けていて、これが最大の項目でした。
Cloudflare Workers のメンテナンス表示にドメインを差し替えてから、CloudFormation スタックを順に削除しました。
2. 別 VPC の遊休 NAT Gateway ¥6,750/月 (30 日間 0 byte)
上記とは別の VPC に、以前 Lambda を VPC 内で動かしていた頃の名残として NAT Gateway が 1 個残っていました。
Lambda 本体は既に削除していたため通信は 30 日間ゼロで、それでも AZ ごとの固定費で月 ¥6,750 かかっていました。
時間課金 ($0.045/h × 24 × 30) + データ処理量 (0 GB) の固定部分だけで、通信していなくても発生します。
3. EIP とパブリック IPv4 の課金 (2024-02 の仕様変更)
2024 年 2 月から、パブリック IPv4 アドレスは 使用中でも $0.005/h の課金対象 になりました。
それ以前は「関連付けられていない EIP のみ課金」だったのですが、仕様変更以降は EC2 に紐付いた EIP も、EC2 に自動割り当てされたパブリック IP も、どちらも同じ料金がかかります。
項目 1・2 に含まれない、稼働を続けている EC2 側の EIP も複数保持していて、それぞれ月 ¥550 くらい、合計で数千円になっていました。
EIP を解放して自動割り当てのパブリック IP に切り替えても料金は変わらないため、削減するにはパブリック IP アドレスを持たない構成 (プライベートサブネット + NAT Gateway か Cloudflare Tunnel) に変えるしかありません。
しかし NAT Gateway 自体の料金が高く (項目 2)、外向きにアクセスする要件があるサーバーで Tunnel を挟むのも当時は面倒だったので、パブリック IP アドレスを持たない構成には変更しませんでした。
代わりに、保持していた EIP はすべて解放して自動割り当てのパブリック IP を受け入れる形にしています。
1 台あたりの課金額は変わりませんが、複数の EIP と関連付け作業が消えて、固定 IP の管理が不要になりました。
IP アドレスが再起動のたびに変わるので、systemd timer で 5 分ごとにスクリプトを実行し、<redacted>.sougen.dev の Cloudflare DNS レコードを更新しています。
4. RDS スナップショットの重複
RDS を CloudFormation で削除した際に、FinalSnapshotIdentifier による最終スナップショットと、自分で撮っていた手動スナップショットが両方残り、合計 40 GB になっていました。
月 ¥570 で、削除するまで料金がかかります。
手元に pg_dump を保管しておくとスナップショット側は消せるのですが、DB 復元経路の予備として今も念のため保持していて、この項目は 2026-09 時点でも残っています。
リソース削除の手順
CloudFormation の二段階削除でバケットを残す
CloudFormation で作ったスタックを削除すると、その中の S3 バケットも基本的には削除されます (デフォルトの DeletionPolicy=Delete)。
中身が空のバケットは削除できますが、中身があるバケットは削除に失敗してスタックが DELETE_FAILED で止まります。
DeletionPolicy: Retain をテンプレートに追加して更新 → 削除が正攻法ですが、多数のスタックを持っている場合は次の 2 段階削除が早いです。
-
空のバケットにダミーのマーカーファイルをアップロードします。
echo "keep" | aws s3 cp - s3://$BUCKET/_retain_marker.txt -
aws cloudformation delete-stack --stack-name Xを実行するとバケット削除に失敗し、DELETE_FAILED になります。 -
再実行時に
--retain-resources <BucketLogicalId1> <BucketLogicalId2>を指定します。aws cloudformation delete-stack --stack-name X \ --retain-resources ImageBucket ServerlessDeploymentBucket
--retain-resources は DELETE_FAILED 状態のときだけ有効です。
最初の削除で渡しても無視されます。
VPC 内 ENI の切り離し待ち
Lambda を VPC に配置していた頃の ENI は、Lambda 本体を削除してから AWS 側が自動で切り離すまで 20〜45 分 かかります (SLA なし)。
CloudFormation で VPC を削除しようとすると "Exceeded attempts to wait" で NotStabilized になるので、時間を置いて再実行します。
手動で ENI を削除しようとしても、Lambda 管理下の ENI (InterfaceType=lambda, RequesterId=AROA...) は削除権限が AWS 側にあり、関連付けの解除もこちらからはできません。
RDS の削除保護
CloudFormation 経由で作った RDS はデフォルトで DeletionProtection: true になっていることが多く、そのままだと Cannot delete protected DB Instance で削除できません。
aws rds modify-db-instance --db-instance-identifier X \
--no-deletion-protection --apply-immediately
を先に実行し、削除保護を解除します。
削減後の月額費用と今後の増額
現在は t4g.small の EC2 が 1 台だけ動いています。
- 月 ¥2,176 の内訳 (2026-09 見込み)
- データ転送 (送信): ¥750
- RDS スナップショット 2 個 (40 GB、手元に pg_dump もあるが念のため保持中): ¥570
- EBS 30 GB: ¥432
- 税: ¥198
- Secrets Manager × 2: ¥120
- S3 リクエスト + CloudWatch: ¥100
- S3 ストレージ 1.69 GB: ¥6
- EC2 t4g.small: ¥0 (無料トライアル適用中)
t4g.small の無料トライアルは 2026-12-31 まで 有効で、それ以降は月 ¥1,815 が上乗せされます。
リザーブドインスタンスやセービングスプランに切り替えるか、そのままオンデマンドで払い続けるかは 2027 年 1 月までに判断する予定です。
残る削減余地
稼働している 1 台の EC2 も、そのうち Cloudflare Workers など別構成に移行して削除する予定です。
そこまで進めば、RDS スナップショット 40 GB と Secrets Manager 2 個も一緒に片付けて、AWS 側の月額は数十円まで減らせます。
2027 年 1 月に t4g.small の無料枠が終わる前に移行を完了したいと考えています。
教訓
- クレジット残高は Console でしか確認できません。実費に戻る時期を予測しづらいため、
UnblendedCost - NetUnblendedCostを月次で監視します。 - 使わなくなったリソースはスタック単位で早めに削除します。特に NAT Gateway と RDS スナップショットは固定費として蓄積します。
- パブリック IPv4 アドレスは使用中でも課金対象になったため、EIP の解放だけでは節約になりません。
- CloudFormation の二段階削除パターンを覚えておきます。
--retain-resourcesは DELETE_FAILED 状態のときだけ有効です。