スケーラブルなデータ登録基盤を構築する:API Gateway → SQS → Lambda → RDS

こんにちは、エンジニアの後河内です。

今回は、とある案件で直面した「一瞬だけ大量のPOSTデータが飛んでくる」という課題に対してのインフラ構築について紹介します。
常に高負荷ではないものの、特定のタイミングで1000件以上のデータが一気に送信される状況がありました。

このようなスパイクアクセスでは、通常時はリソースを節約する瞬間的な負荷に耐えられる構成が求められます。

要件整理

  • ユーザーから送られる大量データを一時的にバッファする
  • 遅延やエラーを最小限に抑える
  • 最終的に RDS(MySQL)へ確実に保存する

採用したアーキテクチャ

API Gateway → SQS → Lambda → RDS(RDS Proxy経由)


この構成を採用した理由

目的

手段

効果

大量データの非同期処理

SQSを中継

スパイク耐性・バッファリング

DB接続の効率化

Lambda + RDS Proxy

同時接続数の制御・安定化

開発・運用のシンプル化

サーバーレス構成

自動スケール・低運用コスト


この構成により、
スパイクが来てもDBを落とさず、処理は順次安定的に流す
という仕組みを実現できました。


本記事では、このアーキテクチャの全体像と構築手順を解説します。

AWS20251110.png

図 構成イメージ

構築手順


ステップ1:RDS(MySQL)とRDS Proxyの準備


1.RDSインスタンス作成

  • エンジン:MySQL 8.0以上
  • パブリックアクセス:オフ
  • Lambda から接続可能な VPC / SG(セキュリティグループ)を設定

                          CREATE TABLE users (
         id SERIAL PRIMARY KEY,
         name VARCHAR(255),
         email VARCHAR(255),
         created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
                          );


2.RDS Proxy作成

  • 対象DB:上記のRDS
  • デフォルト認証スキーム:なし
  • クライアント認証タイプ:MYSQL Native パスワード
  • Identity and Access Management (IAM) ロール IAMロールを作成
  • Secrets Manager のシークレット 新しいシークレット指定
  • IAM 認証 必須
  • VPC・SG:Lambdaと同一
     → Lambdaとの接続安定性・効率性が向上

ステップ2:SQSキューの作成

  • 名前例:data-sqs-queue
  • タイプ:標準キュー
  • DLQ(デッドレターキュー)を設定


ステップ3:Lambda関数の実装(Node.js)

  • ランタイム:Node.js
  • トリガー:SQS (上記で作成したdata-sqs-queue)
  • VPC:RDS Proxyと同一

実行ロールの例

{
 "Version": "2012-10-17",
 "Statement": [
  {
   "Effect": "Allow",
   "Action": [
   "logs:CreateLogGroup",
   "logs:CreateLogStream",
   "logs:PutLogEvents",
   "sqs:ReceiveMessage",
   "sqs:DeleteMessage",
   "sqs:GetQueueAttributes",
   ],
   "Resource": "*"
  },
  {
   "Effect": "Allow",
   "Action": "rds-db:connect",
   "Resource": "arn:aws:rds-db:ap-northeast-1:xxxxxxxxxx:dbuser:prx-xxxxxxxx/*"
  }
 ]
}


Lambdaコード例

import { Signer } from '@aws-sdk/rds-signer';
import mysql2 from 'mysql2/promise';
const RDSConfig = {
 hostname: 'xxxxxxxxxx.ap-northeast-1.rds.amazonaws.com',
  username: 'xxxxxxx',
  region: 'ap-northeast-1',
  database: 'xxxxx',
  port: 3306
};

let config = {};
let lastUpdated = new Date();

export const handler = async (event) => {
    //DB関連処理
    const connection = await createConnection();
    try {
            await connection.connect();

            〜処理〜〜
                
            await connection.end();
    } catch (e) {
        await connection.rollback();
        await connection.end();
        throw e;
    }
};

// DB接続
async function createConnection() {
   const signer = new Signer({
   region: RDSConfig.region,
   hostname: RDSConfig.hostname,
   port: RDSConfig.port,
   username: RDSConfig.username
   });
   const token = await signer.getAuthToken({ username: RDSConfig.username });
   config = {
    host: RDSConfig.hostname,
    user: RDSConfig.username,
    database: RDSConfig.database,
    ssl: 'Amazon RDS',
    password: token,
    authPlugins: { mysql_clear_password: () => () => signer.getAuthToken() }
   };
 }
    return mysql2.createConnection(config);
}

※mysql2は Layer として Lambda に組み込む。組み込み方については下記参考
レイヤーによる Lambda 依存関係の管理
mysql2/promise を使用し、VPC内のLambdaから RDS Proxy 経由で RDSに接続してみた [Node.js]

ステップ4:API Gateway設定(HTTP API)

  • パス:POST /submit
  • 統合先:SQS(data-sqs-queue)

IAMロールの例

{
   "Effect": "Allow",
   "Action": "sqs:SendMessage",
   "Resource": "arn:aws:sqs:ap-northeast-1:xxxxxxxxxx:data-ingestion-queue"
}

ステップ5:テスト


curl -X POST https://xxxxx.execute-api.ap-northeast-1.amazonaws.com/submit \
  -H "Content-Type: application/json" \
  -d '{"name": "田中太郎", "email": "tanaka@example.com"}'


確認ポイント

  • SQSにメッセージが追加される
  • LambdaがCloudWatch Logsに出力を記録
  • RDSのusersテーブルにレコードが挿入される

この構成の強みまとめ

構成要素

メリット

API Gateway → SQS

即時レスポンス&バッファリング

SQS → Lambda

非同期処理でスパイクに強い

Lambda → RDS Proxy

コネクションプールと接続効率化

Node.js

軽量・高速なデータ処理



まとめ

「一瞬だけ高負荷」というパターンは意外と多く、
 常時スケールアップするよりもバッファリング × 非同期処理で解決するのが現実的です。

この構成は、コストを抑えながら高信頼なデータ取り込み基盤を構築したいエンジニアにとって、有力な選択肢になるはずです。

ウシロゴウチ

テックリード/プロジェクトマネージャー

松岡修造さんの日めくりカレンダーを3つ持ってます

関連記事

お仕事のご相談、採用についてなど、お気軽にお問い合わせください。