AWS サーバーレスでクラウドストレージを作った
はじめに
自分専用のファイル共有システムが欲しいと思い、AWS のサーバーレスサービスだけでファイルストレージサービスを作りました。
この記事では、設計で意識したポイントと、実際のアーキテクチャを紹介します。
何を作ったか
Saya は Web ブラウザからファイルのアップロード・ダウンロード・フォルダ管理ができるクラウドストレージサービスです。
主な機能
- ファイルのアップロード / ダウンロード
- フォルダの作成・階層管理
- 複数ファイル / フォルダの一括 ZIP ダウンロード
- ユーザー認証(サインアップ・ログイン・パスワードリセット)
- ユーザープロフィール管理
アーキテクチャ
以下、構成図です。

認証の大部分は Cognito で行い、 ファイル転送は S3 の Presigned URL を Lambda で発行してクライアントと S3 が直接やり取りする仕組みです。
技術スタック
| レイヤー | 技術 |
|---|---|
| バックエンド | C# (.NET 8) / AWS Lambda |
| 認証 | Amazon Cognito + Managed Login v2 |
| API | API Gateway (REST) + Cognito Authorizer |
| ストレージ | Amazon S3 |
設計判断とその理由
2. 認証を Cognito で行う
Cognito の OAuth 2.0 エンドポイントと Managed Login を活用し、認証機能を実現しました。
最終的に認証系の Lambda は TokenFunction 1 つだけになりました。
機能的にもセキュリティ的にも減らせるコードは減らすのが吉です。
AWS のサービスがやってくれることを自前で書く必要はありません。
3. Presigned URL によるファイル転送
ファイルのアップロード・ダウンロードで Lambda を経由すると、いくつかの問題が生じます:
- Lambda のペイロード上限に引っかかる
- 大きなファイルを Lambda のメモリに載せるとコストがかかる
- 転送時間が Lambda の実行時間としてカウントされる
Presigned URL なら、Lambda は URL を発行するだけで、実際のファイル転送はブラウザと S3 が直接行います。
Lambda の実行時間は数十ミリ秒で済み、ファイルサイズの制約も S3 の上限までとなります。
アップロードの流れ:
1. ブラウザ → Lambda: 「file.pdf をアップロードしたい!アップロード先の URL を送れ~」
2. Lambda → ブラウザ: 「アップロード先の Presigned URL だよ。ここに PUT してね~」
3. ブラウザ → S3: 「S3 に PUT するよ~」
4. ブラウザ → Lambda: 「アップロード完了したよ~」
4. フォルダの ZIP ダウンロード
S3 にはフォルダごとダウンロードする機能がありません。
複数ファイルの一括ダウンロードは、Lambda 上で ZIP を生成して一時的に S3 に置き、その Presigned URL を返す方式にしました。
一時 ZIP ファイルは S3 のライフサイクルルールで 1 日後に自動削除されるので、ゴミが溜まることはありません。
セキュリティ
| 対策 | 実装 |
|---|---|
| ブルートフォース防止 | Cognito 標準のロック機能 (5 回失敗: 15 分ロック) |
| API 保護 | Cognito Authorizer による JWT 検証 |
| CORS | AllowedOrigin を特定のドメインに限定 |
| 一時ファイル管理 | S3 ライフサイクルで不要なファイルを 1 日で自動削除 |
コスト
サーバーレス構成なので、利用がなければコストはほぼゼロです。
- Cognito: ESSENTIALS Tier は MAU 10,000 まで無料
- Lambda: 月 100 万リクエストまで無料
- S3: 保存量に応じた従量課金(GB あたり約 $0.025/月)
- API Gateway: 100 万リクエストあたり $3.50
個人利用なら月額数十円〜数百円程度に収まります。
インフラのコード化
インフラ全体を 1 つの template.yaml (AWS SAM) で定義しています。
Cognito User Pool、API Gateway、Lambda 3 関数、S3 バケット、CloudWatch アラーム、SNS — すべてのリソースを 600 行程度の YAML で定義しています。
