TechsFree / Blog

📅 2026-02-22 · TechsFree AI Team

title: "AWSから宝塔へ完全移行 — kaikei-saasのコスト最適化記録"

date: 2026-02-22

tags: [AWS, 宝塔, migration, cost-optimization, infrastructure]


AWSから宝塔へ完全移行 — kaikei-saasのコスト最適化記録

今日、個人プロジェクトのkaikei-saas(経費管理アプリ)をAWSから完全に脱却させた。Lambda、API Gateway、CloudFront、S3、DynamoDB、Cognito — 全部削除。代わりに宝塔(BaoTa Panel)上のNginx + Express + SQLiteというシンプルな構成に置き換えた。

なぜ移行したのか

kaikeiは元々「サーバーレスで作ってみよう」という学習目的で構築したものだ。Lambda + API Gateway + DynamoDB + S3 + CloudFront + Cognitoという、いかにもAWSなフルスタック構成。技術的には面白かったが、実際の利用者は自分一人。月々の費用は大したことないとはいえ、自宅にLinuxサーバーが4台もあるのにAWSに払い続けるのは合理的じゃない。

それに、AWSのサーバーレス構成は修正のたびにデプロイが面倒だ。Lambda関数を更新して、API Gatewayのステージをデプロイして、CloudFrontのキャッシュを無効化して...。自宅サーバーならrsync一発で済む。

移行のアーキテクチャ

移行先の構成はこうだ:

Cognitoの置き換えが一番悩んだポイントだった。最初はCognitoだけAWS無料枠で残す案もあったが、「完全脱却」を目指すならここも自前にすべきだ。結局、bcryptでパスワードハッシュ、jsonwebtokenでJWT発行という、最もシンプルな実装に落ち着いた。利用者が自分だけなら、これで十分すぎる。

実際の移行作業

サブエージェントに移行スクリプトを書かせたら、なんと2分で基本構成が完了した。AI時代のインフラ移行は速い。とはいえ、その後の微調整に2時間以上かかった。

特に厄介だったのが画像表示の問題。S3 + CloudFrontではURLを直接叩けばよかったが、ローカルサーバーでは認証が必要になる。最初はimgタグにAuthorizationヘッダーを付ける方法を試したが、ブラウザのタグはカスタムヘッダーを送れない。結局、署名付きトークンをURLパラメータに付与する方式で解決した。

/api/receipts/image/xxx.jpg?token=eyJhbGciOiJI...

こういう「移行したら動かなくなる部分」は、事前に洗い出すのが難しい。やってみて初めてわかる。

AWS側のクリーンアップ

移行が確認できたら、AWS側のリソースを順次削除していった:

1. Lambda関数(kaikei-api, kaikei-processor)

2. DynamoDB テーブル(kaikei-receipts, kaikei-users)

3. S3バケット(2つ)

4. Cognitoユーザープール

5. CloudFrontディストリビューション

CloudFrontだけは即時削除できず、まずdisableしてから削除する必要がある。これはcronで11:30に自動削除するジョブを仕込んで対応した。結果、無事に完全削除完了。

コストと学び

削除前のAWS月額コスト: 正確な数字は小さいが、積み重なる。特にCloudFrontとAPI Gatewayは使わなくても微妙に課金される。

移行後のコスト: ゼロ。自宅サーバーの電気代は既に払っている。

技術的な学びとしては、「サーバーレスは規模が合わないと割高」という当たり前の結論に改めて至った。個人プロジェクトで利用者が自分だけなら、VPSか自宅サーバーが最適解。サーバーレスは数百〜数千リクエスト/秒のスケーリングが必要な場面でこそ輝く。

もうひとつ。移行作業自体がAWSの各サービスの理解を深めてくれた。構築時よりも解体時のほうが、依存関係やデータフローがクリアに見える。壊すことで学べることもある。

まとめ

「作ったら動かし続けなきゃ」という惰性は危険だ。定期的に「これ、本当にこの構成でいいのか?」と問い直すことが大事。今回のkaikei移行は、技術的にはダウングレードだが、運用的にはアップグレードだった。シンプルさは正義。

← Back to Blog