「Lambda から普通に PostgreSQL に繋いだら、アクセスが増えた瞬間に too many connections でDBが落ちた」——サーバーレスと従来型リレーショナルDBの組み合わせで、必ず最初にぶつかる壁です。Lambda は秒間で数百・数千の実行環境までスケールしますが、RDS/Aurora の同時接続数は有限。この2つの世界観の衝突を設計で吸収しないと、本番は接続枯渇で止まります。
この記事は、AWS Lambda から RDS / Aurora(PostgreSQL・MySQL)へ本番品質で接続するための実装ガイドです。接続枯渇という根本問題から、RDS Proxy・Data API・IAM認証・VPC/NATコスト・Aurora Serverless v2までを一気通貫で解説します。題材として、B2B SaaS(木材流通業界のDX)をPostgreSQL上で本番運用する中で得た接続管理の知見も交えます。Lambda 本体の実行モデルは姉妹記事 AWS Lambda 本番運用ガイド に委ね、本稿は**「リレーショナルDBへの接続」一点**に集中します。
この記事のルール:仕様・パラメータ名・制限は AWS 公式ドキュメント(2026年6月時点) に基づきます。料金(RDS Proxy・NAT等)はリージョン・時期で変わるため、本稿では具体額を断定せず課金モデルを示します。本番投入前に必ず公式(末尾「参考」)で最新値・最新料金を確認してください。
0. メンタルモデル:Lambdaは「接続を共有しない」前提で動く
最初に、なぜ難しいのかを1枚に固定します。
- 同時実行 = 別々の実行環境 = 別々のDB接続。Lambdaは1つの同時リクエストごとに独立した実行環境を割り当てる。それぞれが自分専用のDB接続を開く。
- Lambdaは数千までスケール、RDSの
max_connectionsは有限。例えば1,000同時実行が各1接続を開けば、DBは1,000接続を要求される。これが接続枯渇(connection exhaustion)。 - ハンドラ外の接続再利用は「ウォーム環境1つにつき1接続」まで。これはレイテンシ短縮に効くが、同時実行のファンアウトそのものは解決しない(環境が1,000個あれば接続も最大1,000)。
- だから本番は「接続を共有する層(RDS Proxy)」か「接続を持たない方式(Data API)」を選ぶ。これが本記事の二択です。
公式も明言します——「直接接続は単純なケースで有用、本番ではプロキシを推奨。データベースプロキシは共有接続のプールを管理し、関数がDB接続を枯渇させずに高い同時実行に到達できるようにする」。
1. まず土台:ハンドラ外で接続し、アイドル切断に備える
RDS Proxy や Data API に進む前に、どの方式でも効く基本を押さえます。接続はハンドラ外で1度だけ張り、ウォーム呼び出しで再利用します(公式のベストプラクティス)。
// プールはハンドラ外(INIT)で生成。ウォーム環境内で再利用される。
import { Pool } from "pg";
// 1環境あたり小さなプール。max=1〜数。大きくしても同時実行のファンアウトは別問題
const pool = new Pool({
host: process.env.DB_HOST,
max: 1, // Lambdaは並列処理しない(1呼び出し1処理)ので小さく
idleTimeoutMillis: 0, // Lambda側で勝手に切らない(下のkeep-aliveと併用)
keepAlive: true, // アイドル接続の切断対策
});
export const handler = async (event: { id: string }) => {
// pool.query は同一環境で接続を使い回す(再接続コストを払わない)
const { rows } = await pool.query("SELECT id, total FROM orders WHERE id = $1", [event.id]);
return rows[0] ?? null;
};
公式の注意:Lambda はアイドル接続を時間とともに破棄する。破棄済みの接続を再利用しようとすると接続エラーになるため、keep-alive を有効化し、クエリ前に死活を確認できる設計にします。ただし繰り返しになりますが、**これは「環境内再利用」**であって、同時実行が増えれば接続数も増える——次章のプール層が要る理由です。
2. 本命:Amazon RDS Proxy で接続をプール・共有する
RDS Proxy は、Lambda 群とDBの間に立つフルマネージドの接続プールです。多数のクライアント接続を**少数のDB接続に多重化(multiplex)**し、DBの接続枯渇を防ぎます。フェイルオーバー時も接続を保持して回復性を上げます。
2.1 何が嬉しいか
- 接続のプール・共有:
MaxConnectionsPercent(DBのmax_connectionsに対する割合)でDB側接続の上限を制御。Lambdaが何千スケールしても、DBへの接続はプールの範囲に収まる。 - IAM認証 + Secrets Manager:クライアント(Lambda)はIAMで認証、プロキシはDBへSecrets Manager の資格情報 or IAM DB認証で接続。コードにDBパスワードを持たない。
- 対応エンジン:Aurora(MySQL/PostgreSQL)、RDS for PostgreSQL / MySQL / MariaDB / SQL Server。
// RDS Proxy 経由:接続先をプロキシのエンドポイントにするだけ。IAM認証トークンでパスワードレス
import { Signer } from "@aws-sdk/rds-signer";
import { Pool } from "pg";
const signer = new Signer({
hostname: process.env.PROXY_HOST!, // RDS Proxy のエンドポイント
port: 5432,
username: process.env.DB_USER!,
region: process.env.AWS_REGION!,
});
// 認証トークンは15分で失効するため、接続のたびに発行する(password を関数化)
const pool = new Pool({
host: process.env.PROXY_HOST,
user: process.env.DB_USER,
password: () => signer.getAuthToken(), // ← パスワードの代わりにIAMトークン
ssl: { rejectUnauthorized: true },
max: 1,
});
export const handler = async () => (await pool.query("SELECT now()")).rows[0];
2.2 RDS Proxy の天敵:ピン留め(pinning)
ここが本番で一番ハマる点です。プロキシは接続を多重化しますが、セッション状態に依存する操作を検知すると、そのクライアント接続を特定のDB接続に固定(pinning)します。固定された接続は他のクライアントが再利用できなくなり、多重化の効果が消えます。
公式が挙げる主なピン留めトリガー:
| エンジン共通 | PostgreSQL の例 | MySQL の例 |
|---|---|---|
| 16KB超のSQL文 | SET(変数設定)、PREPARE/DEALLOCATE/EXECUTE、一時テーブル/シーケンス/ビュー作成、カーソル宣言、LISTEN、セッションレベルの advisory lock(pg_advisory_lock) | テーブルロック、GET_LOCK、ユーザー変数設定、一時テーブル作成、プリペアドステートメント |
回避の指針(公式):
- 不要なセッション状態変更を避ける。毎接続で同じ初期化をするなら、プロキシの初期化クエリにまとめる(各クエリで
SETしない)。 - PostgreSQLの advisory lock はセッションレベル(
pg_advisory_lock)でピン留めされるが、トランザクションレベル(pg_advisory_xact_lock)はされない。冪等化・排他制御でロックを使うならトランザクションレベルを選ぶ。 DatabaseConnectionsCurrentlySessionPinnedメトリクスを監視。ピン留めが多ければ、上のトリガーを潰す。
料金モデル:RDS Proxy はプロビジョンドDBではvCPU時間あたり(Aurora ServerlessではACU時間あたり)課金で、課金状態変更後は最低10分の課金。具体額はリージョン・時期で変わるため公式の料金ページで確認してください。「常時少しのトラフィックでも接続を頻繁に開閉する」Lambdaワークロードほど、Proxyの費用対効果が高いのが目安です。
3. もう一つの解:RDS Data API で「接続を持たない」
接続管理そのものを無くす選択肢が RDS Data API です。HTTPのエンドポイントにSDKでSQLを送る方式で、永続接続が不要。Lambda をVPCに入れなくてもDBにアクセスできる(プロキシやENIの設計から解放される)のが大きな利点です。
// Data API:接続プールもVPCも不要。SDKでSQLをHTTP実行。認証はIAM+Secrets Manager
import { RDSDataClient, ExecuteStatementCommand } from "@aws-sdk/client-rds-data";
const rds = new RDSDataClient({}); // 永続接続なし。ハンドラ外で1度だけ生成
export const handler = async (event: { id: string }) => {
const res = await rds.send(new ExecuteStatementCommand({
resourceArn: process.env.CLUSTER_ARN, // Auroraクラスタ
secretArn: process.env.SECRET_ARN, // DB資格情報(Secrets Manager)。コードに持たない
database: "app",
sql: "SELECT id, total FROM orders WHERE id = :id",
parameters: [{ name: "id", value: { stringValue: event.id } }], // パラメータ化でSQLi対策
}));
return res.records ?? [];
};
公式仕様と制限:
- 対応:Aurora PostgreSQL(Serverless v2 + プロビジョンド、13.11/14.8/15.3/16.1/17.4 以降)、Aurora MySQL(3.07 以降)。ライター(書き込み)インスタンスでのみ実行可、Tクラスは非対応。
- 認証:IAM + Secrets Manager。呼び出しに資格情報を渡さない(Secrets Managerが真実源)。
- 制限:レスポンスは1 MiB上限(超えると打ち切り)。大量行の取得には不向き。レイテンシのオーバーヘッドもあるため、短いトランザクション・少量結果に向く。
3.1 RDS Proxy か Data API か
| 観点 | RDS Proxy | Data API |
|---|---|---|
| 接続管理 | プールを共有(接続はある) | 接続なし(HTTP) |
| VPC | 必要(同一VPC) | 不要 |
| 大量結果・ストリーミング | 得意 | 1 MiB上限で不向き |
| 既存のドライバ/ORM | そのまま使える | SDK/専用ドライバが必要 |
| 向くワークロード | 一般的なOLTP、既存資産 | 軽量クエリ、VPCを避けたい、最小構成 |
迷ったら:既存のORM/ドライバ資産があり、まとまった結果を扱うなら RDS Proxy。新規で軽量・VPCの複雑さを避けたいなら Data API(Aurora限定)。
4. VPC とネットワーク:繋がるが「外に出られない」罠とコスト
LambdaからRDSに繋ぐには、RDSと同じVPCにLambdaを置きます(Proxy/直接接続の場合)。ここで2つの落とし穴。
- VPCに入れると、既定でインターネットに出られなくなる。公式明言:「VPCにアタッチするとそのVPC内のリソースしかアクセスできない」「パブリックサブネットに置いてもインターネットアクセスは得られない」。Secrets Manager のパブリックエンドポイントや外部APIに出るには NATゲートウェイが要る。
- NATは時間課金+データ処理(GB)課金。常時稼働でじわじわ効く。Secrets Manager などAWSサービスへは VPCインターフェースエンドポイント(PrivateLink)でNATを回避できる——レイテンシ・コスト・セキュリティの全てで有利。
[Lambda(私有サブネット)] --(同一VPC)--> [RDS Proxy] --> [Aurora]
|
+--(PrivateLink/VPCエンドポイント)--> [Secrets Manager] ← NATを使わない
|
+--(NATゲートウェイ:時間+GB課金)----> [外部API/パブリックEP] ← 必要な時だけ
Hyperplane ENI(VPC関数のネットワーク基盤)はサブネット+SGの組み合わせ単位で共有・再利用され、各65,000接続を捌きます。VPCのコールドスタートが「今は速い」理由と設計の詳細は コールドスタート最適化ガイドのVPC章 に分離しました。
4.1 認証:IAM DB認証という選択
DBの資格情報管理には、Secrets Manager のほかに IAMデータベース認証があります。パスワード不要で、SigV4で生成した15分有効の認証トークンで接続。MySQL/MariaDB/PostgreSQL 対応。ただし公式は「毎秒200新規接続未満で使うこと、それ以上は接続プーリング/RDS Proxyを使え」と推奨。高頻度の新規接続ではRDS Proxyに寄せるのが正解です。
5. どのDBを選ぶか:Aurora Serverless v2 の相性
「サーバーレスのスパイクするLambda」に対して、容量を自動で伸縮するDBが噛み合います。Aurora Serverless v2 は ACU(≈2GiBメモリ)単位で秒刻みに自動スケールし、**最小0 ACU(自動ポーズ)**まで絞れます。
- スケールトゥゼロ(2024年〜):最小ACUを
0にすると、ユーザー接続が無い間はポーズして容量課金が0になり、接続が来ると自動再開(典型15秒・アイドルタイムアウトは5分〜1日)。間欠的なLambda負荷とコスト効率が噛み合う。 - 重要な両立不可:RDS Proxy を関連付けると、プロキシが接続を維持し続けるためインスタンスは自動ポーズしない。「Proxyで接続枯渇を防ぐ」か「スケールトゥゼロで休止中コストを消す」かは、ワークロードで選ぶトレードオフです。
NoSQL(DynamoDB)の方が素直にサーバーレスと噛み合う場面も多いです。リレーショナルが本当に要るのか(結合・トランザクション・既存スキーマ)を含めた選定は DynamoDB vs RDS/Aurora 選定ガイド、接続プーリングの一般論は PgBouncerによるサーバーレス接続プーリング を参照してください。
6. まとめ:Lambda × リレーショナルDB チートシート
- 根本問題:同時実行ごとに別接続。Lambdaは数千スケール、RDSの
max_connectionsは有限 → 接続枯渇。 - 基本:接続/プールはハンドラ外で1度だけ、keep-aliveでアイドル切断に備える。ただしファンアウトは解決しない。
- 本命=RDS Proxy:接続をプール・共有、IAM認証+Secrets Manager でパスワードレス。天敵はピン留め——
SET・一時テーブル・セッションレベルadvisory lockを避け、初期化はプロキシのinitクエリへ、…SessionPinnedを監視。 - 接続を持たない=Data API:HTTPでSQL、VPC不要、Aurora限定、レスポンス1 MiB上限。軽量クエリ向き。
- VPCコスト:私有サブセットのLambdaが外に出るにはNAT(時間+GB)。AWSサービスはPrivateLinkでNAT回避。認証は高頻度ならSecrets Manager/RDS Proxy、低頻度ならIAM DB認証。
- DB選定:Aurora Serverless v2 はスケールトゥゼロでスパイク負荷と好相性。ただしRDS Proxy併用時は自動ポーズしない。
私はB2B SaaSをPostgreSQL上で本番運用する中で、「Lambda/コンテナの同時実行 × 有限なDB接続」という制約に何度も向き合ってきました。接続をプール層で吸収し、秘密情報をコードから排し、NATコストをエンドポイントで削る——この設計規律が、DBを落とさず・安全に・安く運用する土台です。
「自社のサーバーレスがDB接続で詰まる/落ちる、コストが読めない」——接続枯渇の解消からRDS Proxy/Data APIの選定、VPCコスト最適化まで、一人 × 生成AI(Claude Code)の速さで伴走します。 現状の接続設計の診断からでも、お気軽にご相談ください。
参考(公式ドキュメント)
- Using Amazon RDS with Lambda — 直接接続 vs プロキシ、RDS Proxy推奨
- Amazon RDS Proxy — 接続プール、IAM認証、対応エンジン
- Avoiding pinning (RDS Proxy) — ピン留めのトリガーと回避、
DatabaseConnectionsCurrentlySessionPinned - RDS Proxy connections / MaxConnectionsPercent —
max_connectionsに対する上限制御 - Using RDS Data API / limitations — 接続不要、IAM+Secrets Manager、1 MiB上限
- IAM database authentication — 15分トークン、毎秒200接続の目安
- Lambda networking / VPC — VPC内は既定で非インターネット、NATの必要性
- Secrets Manager VPC endpoints (PrivateLink) — NAT回避
- Aurora Serverless v2 auto-pause / scale to zero — 最小0 ACU、RDS Proxy併用時は非ポーズ
- Amazon RDS Proxy pricing — vCPU時間/ACU時間あたりの課金モデル