1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Lambda+RDS構成の可用性と処理速度を向上させるポイント

1
Last updated at Posted at 2026-02-23

はじめに

本記事ではLambdaとRDS(Aurora)構成の
可用性と処理速度を向上させるためのポイントをまとめてみました。
なお、コスト要件で不要になる判断もあると思いますが
本記事ではコスト要件は考えずに理想形とさせていただきます。

確認ポイント①:RDS Proxyを使っていますか?

NGパターン:Lambdaが直接Auroraに接続する

この構成だと、Lambdaの同時実行数が増えたときに
Auroraの同時接続数の上限に引っ掛かり、リクエストが拒否されて未処理のデータが失われてしまいます。

OKパターン:LambdaがRDSProxyを経由してAuroraへアクセスする

RDSProxyを間に入れてあげると接続プールを確立して再利用することで効率的な接続が可能になります。

確認ポイント②:Aurora Serverless v2を使っていますか?

NGパターン:RDS,Auroraを使用する

RDSやAuroraでは自動スケールしないので、Lambdaの同時リクエストが大量に増えたとき
RDSが処理に耐えきれなくなってしまいます。

OKパターン:Aurora Serverless v2を使用する

Aurora Serverless v2を使ってあげることで、DBのオートスケール可能になります。
とわいえ、コストが高いのは否めないので
なるべくNoSQLが使用できないか検討してDynamoDBを使いたいところ。

確認ポイント③:LambdaのDB接続をhandlerの中でやってませんか?

Lambdaはhandler外のコードはコールドスタートの時1回だけ
実行します。逆に言うとhandlerの中はウォームスタートのときも
毎回実行します。DB接続をhandlerの中で実施してしまうとlambda関数が
一回一回DB接続をしてしまい、コネクションを張るのに時間がかかってしまいます。
詳しくは↓を参照ください。

NGパターン:handler内でDB接続をしてしまっている

import json
import os
import boto3
import pymysql

# RDS settings
proxy_host_name = os.environ['PROXY_HOST_NAME']
port = int(os.environ['PORT'])
db_name = os.environ['DB_NAME']
db_user_name = os.environ['DB_USER_NAME']
aws_region = os.environ['AWS_REGION']

# Fetch RDS Auth Token
def get_auth_token():
    client = boto3.client('rds')
    token = client.generate_db_auth_token(
        DBHostname=proxy_host_name,
        Port=port
        DBUsername=db_user_name
        Region=aws_region
    )
    return token

def lambda_handler(event, context):
    token = get_auth_token()
    try:
        connection = pymysql.connect(
            host=proxy_host_name,
            user=db_user_name,
            password=token,
            db=db_name,
            port=port,
            ssl={'ca': 'Amazon RDS'}  # Ensure you have the CA bundle for SSL connection
        )
        
        with connection.cursor() as cursor:
            cursor.execute('SELECT %s + %s AS sum', (3, 2))
            result = cursor.fetchone()

        return result
        
    except Exception as e:
        return (f"Error: {str(e)}")  # Return an error message if an exception occurs 
    

OKパターン:handler外でDB接続をして環境変数に保持している

import json
import os
import boto3
import pymysql

# RDS settings
proxy_host_name = os.environ['PROXY_HOST_NAME']
port = int(os.environ['PORT'])
db_name = os.environ['DB_NAME']
db_user_name = os.environ['DB_USER_NAME']
aws_region = os.environ['AWS_REGION']

# handlerの外で接続を初期化(コールドスタート時のみ実行)
def get_connection():
    client = boto3.client('rds')
    token = client.generate_db_auth_token(
        DBHostname=proxy_host_name,
        Port=port,
        DBUsername=db_user_name,
        Region=aws_region
    )
    return pymysql.connect(
        host=proxy_host_name,
        user=db_user_name,
        password=token,
        db=db_name,
        port=port,
        ssl={'ca': 'Amazon RDS'}
    )

# グローバル変数として接続を保持
connection = get_connection()

def lambda_handler(event, context):
    global connection
    try:
        # 接続が切れている場合は再接続
        if not connection.open:
            connection = get_connection()
        
        with connection.cursor() as cursor:
            cursor.execute('SELECT %s + %s AS sum', (3, 2))
            result = cursor.fetchone()
        return result
        
    except Exception as e:
        return f"Error: {str(e)}"

こうすることでDB接続をグローバル変数にしてウォームスタートした関数
が使いまわしてくれて処理速度が向上します。

まとめ

  • LambdaとRDSと使う時はRDSProxyを使おう!
  • RDSではなく、できるだけAurora Serverless v2を使おう!
  • LambdaのDB接続はハンドラーの外で定義しましょう!
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?