Lambdaを本番に載せた途端「too many connections」で落ちる——サーバーレスとRDBを組み合わせると必ず突き当たる壁です。RDS Proxyがなぜ効くのか、そしてどこで効かないのかを、設定と落とし穴まで踏み込んで整理します。
01なぜコネクションは枯渇するのか
RDS/Auroraの同時接続数には上限があります。MySQLのmax_connectionsやPostgreSQLのmax_connectionsはインスタンスクラスのメモリに比例して決まり、各コネクションはサーバー側でメモリを消費します。ここに、瞬間的に数百〜数千の同時実行までスケールするLambdaを直結すると何が起きるか。Lambdaは実行環境(コンテナ)ごとに独立してDB接続を張るため、同時実行数がそのまま接続数として database に押し寄せます。
しかもLambdaはリクエストが来るたびに短命な接続を開いては閉じる——TLSハンドシェイク、認証、能力交渉といった接続確立のコストを毎回払います。AWSの公式ガイドも、この「頻繁で短命な接続」「大量の接続の開閉」を典型的な非効率として挙げています。接続数が上限に達すれば新規接続はtoo many connectionsで弾かれ、上限に達する手前でも接続管理のためのメモリ・CPUがDB本来のクエリ処理を圧迫します。
DatabaseConnectionsと、接続試行の急増を示すConnectionAttemptsで早めに掴めます。障害になってから気づくのではなく、上限の何割まで来ているかを常時可視化しておくのが第一歩です。02RDS Proxyが挟まると何が変わるか
RDS Proxyは、アプリケーションとデータベースの間に立つフルマネージドのコネクションプーラーです。アプリからは大量の接続を受け付けつつ、DBに対しては少数の長寿命な接続だけを保ち、それらを使い回します。公式ドキュメントはこの再利用をmultiplexing(多重化)と呼び、「1トランザクションの全操作を1本の裏側接続で処理し、次のトランザクションでは別の接続を使える」と説明しています。接続をプールから一時的に取り出す動作がborrowing(借用)、安全に戻せる時点でプールへ返却する、という粒度です。
ポイントは、再利用の単位が「トランザクション」であること。Lambdaのように1リクエスト=1トランザクションで完結するワークロードほど多重化が効き、DB側の実接続本数を劇的に減らせます。Proxy自体はサーバーレスで、複数AZに冗長化されており、コンピュート/メモリはDBインスタンスとは独立しています。
03フェイルオーバーが速くなる仕組み
コネクション管理と並ぶもう一つの効きどころがフェイルオーバーです。Multi-AZ構成でプライマリが落ちると、通常はDNSの切り替わりを待つ必要があり、ローカルDNSキャッシュやTTLの影響で数十秒の断が生じます。RDS Proxyを挟むと、クライアントは常に同じProxyエンドポイント(同じIP)に接続し続けるため、DNS伝播やキャッシュの影響を受けません。公式ドキュメントは、Proxyが「RDS Multi-AZ DBインスタンスのフェイルオーバー時間を最大66%短縮する」と明記しています。
アプリ側が独自の接続プールを持っている場合でも、Proxy経由なら大半の接続はフェイルオーバー中も維持され、キャンセルされるのは「トランザクションやSQL文の実行中」の接続だけです。ライターが不在の間、Proxyは受け付けたリクエストをキューイングし、新プライマリが立ち上がり次第そちらへ流します。Blue/Greenデプロイのスイッチオーバー時にも、Proxyが切り替えを認識してGreen環境へ接続を寄せ、DNS伝播の遅延を避けられます。
04IAM認証とSecrets Managerの連携
RDS Proxyは認証の集約点としても有用です。公式ドキュメントは3つの方式を挙げています。
- データベース認証情報:ProxyがSecrets Managerから取得した資格情報でDBに接続する、最も基本の形。
- 標準IAM認証:クライアント→Proxyの認証をIAMで強制しつつ、Proxy→DBはSecrets Managerの資格情報で接続。DB側がパスワード認証のままでも、アプリからのアクセスにIAMを強制できます。
- エンドツーエンドIAM認証:クライアント→Proxy→DBの全経路をIAM認証に統一。Secrets Managerでの資格情報管理が不要になります。この場合、Proxyに紐づくIAMロールに
rds-db:connect権限を付与します。
Lambdaにとっては旨みが大きい構成です。Lambdaの実行ロールに既にあるIAMをそのまま接続認証に使えるため、DBパスワードをアプリコードや環境変数に埋め込む必要がなくなります。認証情報をSecrets Managerに置く場合は、シークレットのローテーションもProxyが追随するため、資格情報の更新運用が楽になります。SecretsとParameter Storeの使い分けはSecrets Manager vs Parameter Storeで整理しています。
05最大の落とし穴:セッションのピン留め
多重化は「トランザクション間で状態を引き継がない」ことを前提に成り立ちます。ところが、あるセッションが後続の処理に影響する状態変更を行うと、Proxyはそのクライアント接続を特定のDB接続に固定します。これがpinning(ピン留め)です。ピン留めされた接続はセッションが終わるまで他のクライアントに再利用されず、多重化の効果が失われます。ピン留めが多発すると、Proxyを入れているのにDB接続が減らない、という残念な状態になります。
公式ドキュメントが挙げる主な発生条件を、エンジン別に整理します。
- 全エンジン共通:テキストサイズが16KBを超えるステートメント。
- MySQL/MariaDB:
LOCK TABLES等の明示ロック、GET_LOCKによる名前付きロック、ユーザー/システム変数のSET(一部例外あり)、一時テーブル作成、プリペアドステートメント、/*! ... */の実行可能コメントなど。 - PostgreSQL:
SETコマンド全般、PREPARE/DEALLOCATE等のプリペアドステートメント管理、一時テーブル/シーケンス/ビューの作成、カーソル宣言、LISTEN、auto_explain等のライブラリ読み込み、nextval/setval、セッションレベルのアドバイザリロックなど。
SET一発でピン留めされる点に特に注意。コネクションプーリングライブラリがリセットクエリにDISCARD ALLを設定していると、接続返却のたびにピン留めされ、多重化がほぼ無効化されます。プール実装のリセット設定は必ず確認してください。06ピン留めを減らす具体策
ピン留めは「起きているか」を測り、「起こさない」ように設計するのが基本です。まず監視——CloudWatchメトリクスDatabaseConnectionsCurrentlySessionPinnedで、どれだけの接続がピン留めされているかを可視化します。ここが恒常的に高ければ、多重化の恩恵を取りこぼしています。
減らす手立てとして公式が推奨するのは次の通りです。
- 初期化クエリに寄せる:全接続で同じ
SETを打っているなら、それをアプリコードから外し、Proxyの初期化クエリ(セミコロン区切りのSQL文字列)に移す。これで新規接続確立時にProxyが設定を適用し、トランザクション単位の多重化を保てます。 - セッションピン留めフィルタ(MySQL系):セッション変数や設定の変更について、アプリの正しさに影響しないと確信できる範囲でピン留めを免除する。Proxy作成/変更時に指定します。
- 設定を全接続で揃える:Proxyは同じ設定値を持つセッション同士なら接続を再利用できるため、変数・設定を全体で統一しておく。
あわせて、MaxConnectionsPercent(DBの最大接続数に対してProxyが張れる上限の割合)とMaxIdleConnectionsPercent(プールに保持するアイドル接続の上限)、クライアントのアイドル接続を閉じるまでの秒数(既定1,800秒)といったチューニングノブがあります。具体的な既定値・上限はバージョンで変わるため、公式で最新を確認してください。
07アプリ側プールとの関係を整理する
「アプリでコネクションプールを持っているのにProxyも要るのか」という問いは頻出です。両者は競合ではなく、役割が違います。アプリ側プール(HikariCPやpgbouncer、ORMの内蔵プールなど)は、常駐型アプリケーションが自プロセス内で接続を使い回すための仕組みです。一方RDS Proxyは、複数のクライアント・複数の実行環境をまたいで接続を集約します。
- 常駐型のアプリ(ECS/EC2上のWebアプリ):アプリ側プールが基本の主役。Proxyはフェイルオーバー高速化やIAM認証の集約が主目的になります。Proxy経由なら、フェイルオーバー時にプール内の大半の接続が生き残るのも利点です。
- Lambda等のサーバーレス:実行環境ごとにプールが分断され、横断的な集約ができないため、Proxyの集約が本命になります。
両方を併用する場合は、アプリ側プールのサイズを絞りめにし、DB→Proxy→アプリの各段で接続数の上限が破綻しないよう積み上げて設計します。コンテナ側の実務はLambda本番運用の実務もあわせてどうぞ。
08使いどころとコストの判断軸
RDS Proxyの課金は、対象DBの容量に連動します。プロビジョンドDBでは「vCPUあたり・時間あたり」、Aurora ServerlessではACU(Aurora Capacity Unit)あたり・時間あたりの課金です。既定エンドポイントは追加料金なしですが、読み取り専用/読み書きの追加エンドポイントを作るとPrivateLinkインターフェイスエンドポイントの料金がかかります。具体的な単価と最低課金(作成・起動・変更などの状態変化後の最低課金あり)はリージョン・時期で変わるため、公式の料金ページで最新を確認してください。
導入是非は次の判断軸で切り分けると迷いません。
| 状況 | Proxyの効き | 判断 |
|---|---|---|
| Lambdaが大量同時実行でRDBに直結 | 大(集約・IAM認証) | 原則採用 |
| T系など小さめインスタンスで接続過多 | 大(OOM/CPU緩和) | 採用検討 |
| Multi-AZでフェイルオーバー時間が厳しい | 中〜大(最大66%短縮) | RTO要件次第 |
| IAM認証/Secrets集約を後付けしたい | 中(認証の緩衝材) | 採用検討 |
| ピン留め要因が大半(変数SET多用等) | 小(多重化が効かない) | 改修が先/要再検討 |
| 接続数に余裕・低頻度アクセス | 小 | 見送り可 |
Aurora vs RDSの選定そのものを迷っている段階なら、Aurora vs RDSの選定を先に押さえてから、Proxyの要否を重ねると設計がぶれません。
—まとめ
RDS Proxyは「Lambda×RDBのコネクション枯渇」に対する第一選択であり、同時にフェイルオーバー高速化とIAM認証の集約という副次的な価値も持ちます。ただし万能ではありません。多重化はトランザクション間で状態を持ち越さないことが前提で、変数のSETや一時テーブル、プリペアドステートメントなどでピン留めが多発すると効果が消えます。導入前にDatabaseConnectionsCurrentlySessionPinnedを含む挙動を実測し、アプリ側プールとの役割分担とコストを見極めることが、投資を無駄にしない鍵です。設計判断に迷われたらお問い合わせください。