ANTIGRAVITY LABEN
記事一覧/アプリ開発
アプリ開発/2026-03-28中級

Antigravity × AWS Lambda でサーバーレスAPIを構築する実践ガイド — DynamoDB・API Gateway・S3連携

Antigravity のAIエージェントを活用してAWS Lambda上にサーバーレスAPIを構築する方法を実践的に解説。DynamoDB・API Gateway・S3との統合、IaCによるインフラ管理まで網羅します。

antigravity436aws-lambdaserverless2dynamodbapi-gateways3tutorial4

取り組みの背景 — なぜ Antigravity × AWS Lambda なのか

サーバーレスアーキテクチャは、インフラ管理の負担を大幅に軽減しながらスケーラブルなAPIを構築できる手法として、多くの開発者に支持されています。中でも AWS Lambda は、イベント駆動型の関数実行基盤として業界標準の地位を確立しました。

しかし、Lambda 関数の作成・API Gateway の設定・DynamoDB テーブルの定義・IAMポリシーの構成など、AWS サーバーレス開発には多くの設定作業が伴います。ここで Antigravity のAIエージェントが力を発揮します。エージェントに指示を出すだけで、ボイラープレートコードの生成からインフラ定義まで一貫して自動化できるのです。

ここではAntigravity を使って AWS Lambda 上にサーバーレスREST APIを構築する手順を、実際のコード例とともにステップバイステップで解説します。DynamoDB によるデータ永続化、API Gateway によるエンドポイント公開、S3 によるファイルストレージ連携まで、実用的なサーバーレスバックエンドの構築方法を学べます。

この記事の対象読者:

  • AWS の基本的なサービス(Lambda, DynamoDB, S3)を聞いたことがある方
  • Antigravity でバックエンド開発を効率化したい方
  • サーバーレスアーキテクチャに興味がある中級開発者

前提環境の準備

Antigravity でAWSサーバーレス開発を始めるには、いくつかのツールを事前にセットアップしておく必要があります。

必須ツール:

  • Antigravity(最新版推奨)
  • AWS CLI v2(aws configure で認証済み)
  • Node.js 20 LTS 以上
  • AWS SAM CLI または Serverless Framework

Antigravity のターミナルで以下のコマンドを実行し、環境を確認しましょう。

# AWS CLI の認証状態を確認
aws sts get-caller-identity
 
# 出力例:
# {
#   "UserId": "AIDACKCEVSQ6C2EXAMPLE",
#   "Account": "123456789012",
#   "Arn": "arn:aws:iam::123456789012:user/dev-user"
# }
 
# SAM CLI のバージョンを確認
sam --version
# SAM CLI, version 1.120.0

AWS CLIの認証が完了していない場合は、aws configure コマンドでアクセスキーとリージョンを設定してください。ここでは ap-northeast-1(東京リージョン)を使用します。

プロジェクトの初期化 — Antigravity でスキャフォールド

まずは Antigravity のエージェントにプロジェクトの雛形を生成させます。エージェントチャットで以下のように指示します。

AWS SAM を使って、DynamoDB をデータストアとする
REST API プロジェクトを初期化してください。
ランタイムは Node.js 20、TypeScript で構築します。
エンドポイントは CRUD 操作(GET/POST/PUT/DELETE)を用意してください。

Antigravity のエージェントが template.yaml(SAM テンプレート)と Lambda 関数のコードを自動生成します。生成されたプロジェクト構造を確認しましょう。

serverless-api/
├── template.yaml           # SAM テンプレート(インフラ定義)
├── src/
│   ├── handlers/
│   │   ├── createItem.ts   # POST /items
│   │   ├── getItem.ts      # GET /items/{id}
│   │   ├── listItems.ts    # GET /items
│   │   ├── updateItem.ts   # PUT /items/{id}
│   │   └── deleteItem.ts   # DELETE /items/{id}
│   ├── lib/
│   │   ├── dynamodb.ts     # DynamoDB クライアントヘルパー
│   │   └── response.ts     # API レスポンスユーティリティ
│   └── types/
│       └── item.ts         # 型定義
├── tsconfig.json
├── package.json
└── samconfig.toml

SAM テンプレートの構成 — インフラをコードで定義する

template.yaml は AWS のインフラをコードとして定義するファイルです。Antigravity が生成したテンプレートのポイントを見ていきましょう。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Serverless REST API with DynamoDB
 
Globals:
  Function:
    Timeout: 15
    Runtime: nodejs20.x
    MemorySize: 256
    Environment:
      Variables:
        TABLE_NAME: !Ref ItemsTable
        BUCKET_NAME: !Ref AssetsBucket
 
Resources:
  # API Gateway
  ApiGateway:
    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
      Cors:
        AllowMethods: "'GET,POST,PUT,DELETE,OPTIONS'"
        AllowHeaders: "'Content-Type,Authorization'"
        AllowOrigin: "'*'"
 
  # DynamoDB テーブル
  ItemsTable:
    Type: AWS::DynamoDB::Table
    Properties:
      TableName: serverless-items
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: id
          AttributeType: S
      KeySchema:
        - AttributeName: id
          KeyType: HASH
 
  # S3 バケット(ファイルアップロード用)
  AssetsBucket:
    Type: AWS::S3::Bucket
    Properties:
      BucketName: !Sub "${AWS::StackName}-assets"
      CorsConfiguration:
        CorsRules:
          - AllowedMethods: [GET, PUT]
            AllowedOrigins: ['*']
            AllowedHeaders: ['*']
 
  # Lambda 関数(Create)
  CreateItemFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handlers/createItem.handler
      Events:
        CreateItem:
          Type: Api
          Properties:
            RestApiId: !Ref ApiGateway
            Path: /items
            Method: post
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref ItemsTable
 
  # Lambda 関数(List)
  ListItemsFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: src/handlers/listItems.handler
      Events:
        ListItems:
          Type: Api
          Properties:
            RestApiId: !Ref ApiGateway
            Path: /items
            Method: get
      Policies:
        - DynamoDBReadPolicy:
            TableName: !Ref ItemsTable

ここでのポイントは、DynamoDB の BillingMode: PAY_PER_REQUEST(オンデマンド課金)を選択している点です。開発初期やトラフィックが予測しにくいプロジェクトでは、プロビジョニングモードよりもコスト効率が良くなります。

Lambda 関数の実装 — TypeScript で型安全に

次に、Lambda 関数の具体的な実装を見ていきます。まずはDynamoDB クライアントのヘルパーモジュールから始めます。

// src/lib/dynamodb.ts
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import {
  DynamoDBDocumentClient,
  PutCommand,
  GetCommand,
  ScanCommand,
  UpdateCommand,
  DeleteCommand,
} from "@aws-sdk/lib-dynamodb";
 
// DynamoDB Document Client を初期化
const client = new DynamoDBClient({ region: "ap-northeast-1" });
const docClient = DynamoDBDocumentClient.from(client);
 
const TABLE_NAME = process.env.TABLE_NAME || "serverless-items";
 
// アイテムを作成
export async function createItem(item: Record<string, unknown>) {
  await docClient.send(
    new PutCommand({
      TableName: TABLE_NAME,
      Item: item,
    })
  );
  return item;
}
 
// IDでアイテムを取得
export async function getItemById(id: string) {
  const result = await docClient.send(
    new GetCommand({
      TableName: TABLE_NAME,
      Key: { id },
    })
  );
  return result.Item;
}
 
// 全アイテムを取得(ページネーション対応)
export async function listAllItems(limit = 20, lastKey?: string) {
  const params: Record<string, unknown> = {
    TableName: TABLE_NAME,
    Limit: limit,
  };
  if (lastKey) {
    params.ExclusiveStartKey = { id: lastKey };
  }
  const result = await docClient.send(new ScanCommand(params));
  return {
    items: result.Items || [],
    nextKey: result.LastEvaluatedKey?.id,
  };
}
 
// アイテムを削除
export async function deleteItemById(id: string) {
  await docClient.send(
    new DeleteCommand({
      TableName: TABLE_NAME,
      Key: { id },
    })
  );
}

続いて、POST エンドポイントの Lambda ハンドラーを実装します。

// src/handlers/createItem.ts
import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
import { randomUUID } from "crypto";
import { createItem } from "../lib/dynamodb";
import { success, error } from "../lib/response";
 
export async function handler(
  event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> {
  try {
    // リクエストボディをパース
    const body = JSON.parse(event.body || "{}");
 
    // バリデーション
    if (!body.name || !body.description) {
      return error(400, "name と description は必須です");
    }
 
    // アイテムを作成
    const item = {
      id: randomUUID(),
      name: body.name,
      description: body.description,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
    };
 
    const created = await createItem(item);
 
    // 201 Created で返却
    return success(201, created);
  } catch (err) {
    console.error("CreateItem error:", err);
    return error(500, "アイテムの作成に失敗しました");
  }
}

レスポンスユーティリティも Antigravity に生成させます。CORS ヘッダーの設定漏れは頻出バグなので、ここで一元管理するのがポイントです。

// src/lib/response.ts
const headers = {
  "Content-Type": "application/json",
  "Access-Control-Allow-Origin": "*",
  "Access-Control-Allow-Methods": "GET,POST,PUT,DELETE,OPTIONS",
};
 
export function success(statusCode: number, body: unknown) {
  return {
    statusCode,
    headers,
    body: JSON.stringify(body),
  };
}
 
export function error(statusCode: number, message: string) {
  return {
    statusCode,
    headers,
    body: JSON.stringify({ error: message }),
  };
}

S3 連携 — 署名付きURLでファイルアップロード

サーバーレスAPIでファイルアップロードを実装する場合、Lambda を経由せずに S3 の署名付きURL(Presigned URL)を活用するのがベストプラクティスです。Lambda のペイロード制限(6MB)を回避でき、大容量ファイルも効率的に扱えます。

// src/handlers/getUploadUrl.ts
import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3";
import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
import { APIGatewayProxyEvent, APIGatewayProxyResult } from "aws-lambda";
import { randomUUID } from "crypto";
import { success, error } from "../lib/response";
 
const s3 = new S3Client({ region: "ap-northeast-1" });
const BUCKET = process.env.BUCKET_NAME!;
 
export async function handler(
  event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> {
  try {
    const body = JSON.parse(event.body || "{}");
    const contentType = body.contentType || "application/octet-stream";
    const key = `uploads/${randomUUID()}`;
 
    // 署名付きURLを生成(有効期限: 15分)
    const command = new PutObjectCommand({
      Bucket: BUCKET,
      Key: key,
      ContentType: contentType,
    });
    const uploadUrl = await getSignedUrl(s3, command, { expiresIn: 900 });
 
    return success(200, {
      uploadUrl,    // クライアントはこのURLにPUTでアップロード
      key,          // アップロード後のオブジェクトキー
      expiresIn: 900,
    });
  } catch (err) {
    console.error("GetUploadUrl error:", err);
    return error(500, "アップロードURLの生成に失敗しました");
  }
}

クライアント側からは、取得した uploadUrl に対して PUT リクエストでファイルを直接アップロードします。

// クライアント側の実装例
async function uploadFile(file: File) {
  // 1. 署名付きURLを取得
  const res = await fetch("/items/upload-url", {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({ contentType: file.type }),
  });
  const { uploadUrl, key } = await res.json();
 
  // 2. S3 に直接アップロード
  await fetch(uploadUrl, {
    method: "PUT",
    headers: { "Content-Type": file.type },
    body: file,
  });
 
  return key; // DynamoDB のレコードに紐づけて保存
}

ローカル開発とデバッグ — SAM CLI でテスト

デプロイ前にローカルでAPIを動作確認するのは、サーバーレス開発の基本です。AWS SAM CLI を使えば、Lambda 関数をローカルで実行できます。

# ローカルで API Gateway + Lambda を起動
sam local start-api --warm-containers EAGER
 
# 出力例:
# Mounting CreateItemFunction at http://127.0.0.1:3000/items [POST]
# Mounting ListItemsFunction at http://127.0.0.1:3000/items [GET]
# ...
 
# 別ターミナルからテストリクエストを送信
curl -X POST http://127.0.0.1:3000/items \
  -H "Content-Type: application/json" \
  -d '{"name": "テストアイテム", "description": "SAM ローカルテスト"}'
 
# 期待する出力:
# {
#   "id": "a1b2c3d4-...",
#   "name": "テストアイテム",
#   "description": "SAM ローカルテスト",
#   "createdAt": "2026-03-28T12:00:00.000Z",
#   "updatedAt": "2026-03-28T12:00:00.000Z"
# }

Antigravity のエージェントにデバッグを依頼することもできます。「Lambda 関数の createItem が 500 エラーを返す。DynamoDB との接続を確認して」と伝えれば、エージェントがログを解析し、IAM ポリシーの不足や環境変数の設定漏れを特定してくれます。

デプロイと本番運用のベストプラクティス

ローカルテストが完了したら、実際に AWS にデプロイします。

# 初回デプロイ(ガイド付き)
sam deploy --guided
 
# 2回目以降
sam deploy
 
# デプロイ完了後、エンドポイントURLが表示される
# Outputs:
# ApiUrl: https://abc123.execute-api.ap-northeast-1.amazonaws.com/prod

本番運用で押さえておくべきポイントをいくつか紹介します。

コールドスタート対策: Lambda 関数は一定時間アクセスがないとコンテナが破棄され、次回起動時に遅延(コールドスタート)が発生します。レイテンシが重要なAPIでは Provisioned Concurrency を設定するか、関数の初期化コードを最小限に抑えましょう。

# template.yaml でのProvisioned Concurrency設定
CreateItemFunction:
  Type: AWS::Serverless::Function
  Properties:
    # ... 既存の設定
    ProvisionedConcurrencyConfig:
      ProvisionedConcurrentExecutions: 5

モニタリング: CloudWatch Logs は自動的に有効になりますが、構造化ログを出力するとデバッグが格段に楽になります。Antigravity に「Lambda 関数に構造化ログ(JSON形式)を追加して」と指示すれば、@aws-lambda-powertools/logger を使ったログ実装を生成してくれます。

セキュリティ: IAM ポリシーは最小権限の原則に従い、各 Lambda 関数に必要最小限の権限のみ付与します。SAM テンプレートの Policies セクションで DynamoDBCrudPolicyS3ReadPolicy など、SAM のポリシーテンプレートを活用するのが安全です。

さらに詳しいセキュリティパターンについては、Antigravity エージェントでセキュアな API バックエンドを構築する実践ガイド で認証・バリデーション・レート制限の実装を詳しく解説しています。

まとめ

Antigravity × AWS Lambda の組み合わせは、サーバーレスAPIの開発速度を大幅に向上させます。SAM テンプレートの生成、Lambda 関数の TypeScript 実装、DynamoDB ヘルパーの作成、S3 署名付きURLの実装まで、AIエージェントが一貫してサポートしてくれるため、AWSの設定作業に時間を取られることなく、ビジネスロジックの実装に集中できます。

サーバーレスアーキテクチャの次のステップとして、イベント駆動型のマイクロサービスに発展させたい方には、Antigravity × Event-Driven Architecture 実践ガイド も参考になるでしょう。

シェア

お読みいただきありがとうございます

Antigravity Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

アプリ開発2026-03-25
Antigravity × Upstash Redis:エッジキャッシュとレート制限で高速・安全なAPIを構築する
Antigravity と Upstash Redis を組み合わせて、Cloudflare Workers 上でエッジキャッシュとレート制限を実装する方法をステップバイステップで解説します。
アプリ開発2026-03-24
AI Studio × Antigravity × Firebase でリアルタイムマルチプレイヤーアプリを構築する方法
Google AI Studio の新しいフルスタック Vibe Coding 機能と Antigravity、Firebase を組み合わせて、リアルタイムマルチプレイヤーアプリをゼロから構築するステップバイステップガイドです。
アプリ開発2026-07-18
「Compose ファースト」の後で、View の画面をどの順に移すか — 画面数ではなく変更頻度で決める
Google が Android 開発を Compose ファーストと表明しました。View ベースの画面をどの順で移すかを、画面数ではなく git の変更履歴から決める判断軸と、実際に動かしたスコアリングスクリプトをまとめます。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →