はじめに
AWS Lambda と RDS(PostgreSQL)を組み合わせると、サーバレスでデータベース操作が可能なバックエンドを構築できます。本記事では、VPC 内のプライベートサブネットに配置した RDS に Lambda から接続し、Node.js を使って SQL を実行するまでの手順を解説します。
特に以下のポイントを重点的に紹介します:
-
VPC、サブネット、NATゲートウェイの設定
-
RDS(PostgreSQL)の作成とサブネットグループ設定
-
Lambda 関数の VPC 配置とセキュリティグループ設定
-
Lambda レイヤーを利用した Node.js モジュールの管理
-
Lambda から RDS への安全な接続方法
開発環境を前提に、テスト用に最小限の構成で動作確認まで行う手順をまとめています。
手順
1.VPCなどの作成
VPCなどを選択することで、必要なサブネットなどを自動で作成してくれます。
IPv4 CIDRブロックは他のリソースと競合するのを避けるため、デフォルト(10.0.0.0/16)ではなく、変更しておきましょう。

今回、Lambdaがインターネットアクセスできるようにしたいので、NATゲートウェイを作成します。

これでしばらく待つと作成されます。
2. DBの作成(RDS)
VPCは項1で作成したものを選択する。
サブネットには、項1で作成されたPrivateサブネットを2つ選択する。

これでサブネットグループの作成は完了。
エンジンタイプはPostgreSQLにしました。(必要に応じて選択してください)

テスト用なので無料利用枠にします。
本番用を選択すると、障害に備えて複数インスタンスを立ててスタンバイを用意するなどして、めちゃくちゃリッチな構成になります。一時間で2$以上の激高になるので気を付けてください。

セルフマネージドを選択して、パスワードを設定します。
Secrets Manager を選択すると、DBのユーザ名・パスワードなどを安全に保管・自動ローテーションしてくれます。

項1で作成したVPCを選択、サブネットグループは先ほど作成したものを選択する。
セキュリティグループを作成しておく。

追加設定でDB名を指定して、初期DBを作成しておきましょう。

補足:
AWS Secrets Manager
目的は「認証情報を安全に管理・自動更新すること」
例えば RDS のユーザー名・パスワードを Secrets Manager に登録しておくと、
- Lambda や ECS から安全に取得できる(IAM認証ベースでアクセス制御)
- RDSのパスワードを自動ローテーション(再生成+DB反映)できる
- 暗号化はKMS連携で自動化
- アプリ側でパスワードをハードコードせずに済み、セキュリティと運用効率が大幅に向上
3. Lambda関数の作成
まず、Lambdaに適用するセキュリティグループを作成します。

項1で作成したVPCを選択する。
アウトバウンドルールで(0.0.0.0/0)を追加。(インターネットアクセスを許可するため)
また、項2でRDSに割り当てたセキュリティグループも追加する。

関数名を入力して作成
ランタイムはnode.jsにします。バックエンドをpythonにしたければ、pythonを選択してください。

その他の構成からVPCを有効化し、項1で作成したVPCを選択する。
サブネットにはPrivateサブネットを2つ選択し、セキュリティグループは先ほど作成したものを選択する。

これで作成されます。
以下は、中身の説明です。
ディレクトリ構成
testFunction/
├── index.mjs # Lambdaのエントリーポイント(handler)
└── db.mjs # DB接続やSQL実行ロジックを定義
以下、サンプルコードです。
Lambda 関数のメイン処理
import { query } from "./db.mjs"
export const handler = async (event) => {
try {
// テストイベントで SQL を指定
const sql = event.sql || "SELECT NOW()";
const params = event.params || [];
// RDS にクエリ実行
const res = await query(sql, params);
return {
statusCode: 200,
body: JSON.stringify(res.rows),
};
} catch (err) {
console.error(err);
return {
statusCode: 500,
body: JSON.stringify({ error: err.message }),
};
}
};
DB接続ロジック
import { createRequire } from "module";
const require = createRequire(import.meta.url);
const pg = require("pg");
const { Pool } = pg;
const pool = new Pool({
host: process.env.DB_HOST,
user: process.env.DB_USER,
password: process.env.DB_PASSWORD,
database: process.env.DB_NAME,
port: process.env.DB_PORT || 5432,
ssl: { rejectUnauthorized: false },
});
export async function query(text, params) {
const client = await pool.connect();
try {
const res = await client.query(text, params);
return res;
} finally {
client.release();
}
}
ssl: { rejectUnauthorized: false } は RDS の証明書を信頼するための設定です(開発環境では安全です)。
本番では ACM 証明書を利用した HTTPS 経由で安全に接続します。
Lambda環境変数の設定
DB_HOST: エンドポイントを設定(RDSの接続とセキュリティから確認できます)
DB_PORT: ポート番号を設定(RDSの接続とセキュリティから確認できます)
DB_USER: 項2でRDS作成時に指定した名称(デフォルト postgres)
DB_PASSWORD: 項2でRDS作成時に指定したパスワード
DB_NAME: 項2の追加設定で決めた任意のDB名
Lambdaレイヤーの作成
下記、ローカル作業
mkdir pg-layer
Dockerfileを作成
pg-layer配下に配置
# Lambda公式 Node.js 22 実行環境イメージ
FROM public.ecr.aws/lambda/nodejs:22
# zip コマンドをインストール
RUN microdnf install -y zip && microdnf clean all
# Layerフォルダ作成
RUN mkdir -p /opt/nodejs
WORKDIR /opt/nodejs
# pg ライブラリをインストール
RUN npm init -y && npm install pg
# ZIP化
WORKDIR /opt
RUN zip -r /layer.zip nodejs
cd pg-layer
wsl
## コンテナのビルド
sudo docker build -t lambda-layer .
## コンテナ内で作成された Lambda Layer(/layer.zip)をローカル環境にコピー
sudo docker run --rm -v $(pwd):/out --entrypoint /bin/bash lambda-layer -c "cp /layer.zip /out/"
コマンドの補足:
- --entrypoint /bin/bash の役割
Lambda の公式 Node.js イメージ(public.ecr.aws/lambda/nodejs:22)には、
デフォルトで Lambda 実行用のエントリーポイントが設定されています。
つまり、何も指定せずにコンテナを実行すると、
Node.js の Lambda ランタイムとして起動してしまい、
シェル操作や cp コマンドが使えません。
そのため、上記のように --entrypoint /bin/bash を指定し、一時的にエントリーポイントを Bash に差し替えています。
ホスト側にzipファイルが作成されるので、これを基にLambda Layerを作成する。
こうして作成したLambda Layerを作成したLambda関数に追加する。
コードタブの一番下にある

何回か失敗してしまったので、画像はバージョン6を選択していますが、1しかないと思います。

4. RDSのインバウンドルール設定
Lambdaに割り当てているセキュリティグループを選択します。
これで、RDSがLambdaからの通信を受け取れるようになります。
ちなみに伏せている部分は自分のグローバルIPアドレスです。
RDS作成時デフォルトで自身のIPアドレスからのアクセス許可が設定されます。
しかし、今回はPrivateサブネットに配置しているため、自身のIPアドレスからも直接接続することはできません。

5. 動作確認
{
"sql": "SELECT NOW()"
}
このように現在時刻が返ってきたら成功です。
おつかれさまでした!
最後に
本記事では、AWS 上で Lambda からプライベートサブネット内の RDS(PostgreSQL)に接続する方法を紹介しました。
操作が多くて結構内容が散らかってしまった気がします。もっと色々書きたい内容ありましたが、今回はやめておきます。











