FastAPI を AWS Lambda にデプロイする方法 – Mangum設定ガイド

目次

FastAPI AWS Lambda デプロイ – サーバーレス環境で実行する

FastAPI を Lambda で動かす

FastAPI は「ASGI(非同期)フレームワーク」であり、通常は Uvicorn サーバーで動作します。しかし、AWS Lambda のようなサーバーレス環境では、固定的なサーバーを持たないため、工夫が必要です。

今回は、FastAPI アプリケーションを AWS Lambda にデプロイしてサーバーレスで実行する方法についてまとめておきたいと思います。

もしご自身で先に公式ドキュメントをご覧になられる方は下のリンクから眺めてみてください。
AWS Lambda – Japan ー 公式ドキュメント(日本語)

対象となる方

  • FastAPI を AWS Lambda で動かしたい方
  • サーバーレスアーキテクチャに興味のある方
  • コスト削減を目指している方

 ※ このドキュメントは FastAPI 0.100 以上、AWS Lambda で実行することを想定しています。

Lambda と Uvicorn サーバーの違い

従来の Uvicorn サーバー

$ uvicorn main:app --host 0.0.0.0 --port 8000

# ← サーバーが常に起動状態で待機
# リクエスト来たら処理 → レスポンス返す
# を繰り返す

利点: シンプル、遅延なし

課題: 24/7 起動のためコスト高い

Lambda での動作

# Lambda では Uvicorn のような「待機サーバー」ではなく、
# 「関数実行」という形式で動作する

# イベント受信 → 関数実行 → レスポンス返す
# この間だけ課金される(秒単位)

from mangum import Mangum
from fastapi import FastAPI

app = FastAPI()

@app.get("/api/hello")
async def hello():
    return {"message": "Hello"}

# Lambda 用ハンドラ
handler = Mangum(app)

利点: 使用時間だけ課金(低コスト)、自動スケーリング

課題: コールドスタート遅延(初回数秒)

Mangum – ASGI 変換ツール

FastAPI は ASGI フレームワークですが、Lambda は AWS 固有のイベント形式(ALB Events)を使用します。Mangum

pip install mangum
from fastapi import FastAPI
from mangum import Mangum

app = FastAPI()

@app.get("/api/users")
async def list_users():
    return {"users": [{"id": 1, "name": "John"}]}

@app.post("/api/users")
async def create_user(name: str):
    return {"id": 2, "name": name}

# Lambda ハンドラ
# Mangum が ALB イベントを ASGI リクエストに変換
# FastAPI が処理 → ASGI レスポンスを Lambda イベントレスポンスに変換
handler = Mangum(app)

Lambda デプロイメント

では、実際にデプロイしてみましょう。

ステップ 1: プロジェクト構成

project/
├── main.py              # FastAPI アプリケーション
├── requirements.txt
├── samconfig.toml       # SAM(AWS)設定
└── template.yaml        # Lambda/API Gateway 定義

ステップ 2: requirements.txt

fastapi==0.104.1
mangum==0.15.1
pydantic==2.5.0
sqlalchemy==2.0.23
asyncpg==0.29.0

ステップ 3: main.py

from fastapi import FastAPI, HTTPException, Depends
from sqlalchemy.ext.asyncio import AsyncSession
from mangum import Mangum
import os

app = FastAPI()

# DB セッション設定(Lambda の場合は NullPool を使用)
from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker
from sqlalchemy.pool import NullPool

engine = create_async_engine(
    os.environ["DATABASE_URL"],
    poolclass=NullPool,
)

async_session_maker = async_sessionmaker(engine, expire_on_commit=False)

async def get_db():
    async with async_session_maker() as session:
        yield session

# エンドポイント
@app.get("/api/health")
async def health_check():
    return {"status": "ok"}

@app.get("/api/users")
async def list_users(db: AsyncSession = Depends(get_db)):
    from sqlalchemy import select
    from models import User

    result = await db.execute(select(User))
    users = result.scalars().all()
    return {"users": users}

# Lambda ハンドラ
handler = Mangum(app)

ステップ 4: Lambda 関数をデプロイ

# AWS CLI でデプロイ
aws lambda create-function \
  --function-name fastapi-app \
  --runtime python3.11 \
  --role arn:aws:iam::ACCOUNT_ID:role/lambda-execution-role \
  --handler main.handler \
  --zip-file fileb://lambda-function.zip \
  --timeout 30 \
  --memory-size 512 \
  --environment "Variables={DATABASE_URL=postgresql+asyncpg://...}"

実装例:Lambda + RDS(Aurora)

Lambda でよく使われるのが AWS RDS(関係データベース)。VPC を経由して接続します。

import os
from fastapi import FastAPI, Depends
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine, async_sessionmaker
from sqlalchemy.pool import NullPool

app = FastAPI()

# RDS の接続文字列は Lambda 環境変数から読み込み
DATABASE_URL = os.environ.get(
    "DATABASE_URL",
    "postgresql+asyncpg://user:pass@rds-instance.abcdefg.ap-northeast-1.rds.amazonaws.com/dbname"
)

engine = create_async_engine(
    DATABASE_URL,
    poolclass=NullPool,
    connect_args={
        "timeout": 10,
        "command_timeout": 10,
    },
)

async_session_maker = async_sessionmaker(
    engine,
    class_=AsyncSession,
    expire_on_commit=False,
)

async def get_db():
    async with async_session_maker() as session:
        yield session

# エンドポイント
@app.get("/api/users")
async def list_users(db: AsyncSession = Depends(get_db)):
    from sqlalchemy import select, text

    result = await db.execute(select(text("SELECT * FROM users LIMIT 10")))
    return {"users": result.fetchall()}

from mangum import Mangum
handler = Mangum(app)

コールドスタート対策

Lambda の「コールドスタート」(初回実行の遅延)を減らす方法:

対策効果実装
メモリ増加⭐⭐⭐512MB → 1024MB に変更
Lambda Layers⭐⭐依存パッケージを別レイヤーに
Provisioned Concurrency⭐⭐⭐常にウォームに保つ(コスト増)
コード最適化⭐不要なインポートを削除
# Provisioned Concurrency の設定例
# 常に 5 個のコンテナをウォーム状態に保つ
# → コールドスタートなし

aws lambda put-provisioned-concurrency-config \
  --function-name fastapi-app \
  --provisioned-concurrent-executions 5 \
  --qualifier LIVE

本番デプロイのチェックリスト

  • 環境変数を Lambda に設定した
  • IAM ロールに RDS アクセス権限がある
  • VPC 設定で RDS に接続できる
  • タイムアウト時間を適切に設定した(30 秒以上推奨)
  • メモリサイズを 512MB 以上に設定した
  • CloudWatch Logs を確認できる環境にある

まとめ

以上で FastAPI を AWS Lambda にデプロイする方法について説明を終えたいと思います。

Mangum と Lambda を組み合わせることで、小規模な API であればサーバーレス運用で、ほぼ無料に近い価格帯で運用できます。コールドスタートが気になる場合は Provisioned Concurrency を検討し、本番運用の負荷に応じて使い分けましょう。

FastAPI の非同期パワーと Lambda のスケーラビリティを組み合わせることで、スケーラブルで低コストな API を実現できますね ^^v 

ということで、ではまた〜

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

この記事を書いた人

Web Developer / Educator