更新: 2026年03月 · 10 分で読める · 5,225 文字
AWS Lambdaのタイムアウトエラーを解決する実装パターン
AWS Lambdaの実行時間制限により、長時間かかる処理が突然中断される問題に直面していませんか。この記事では、タイムアウトの仕組みを理解した上で、非同期処理、バッチ処理分割、ステートマシンといった具体的な解決策を実装レベルで解説します。
AWS Lambdaのタイムアウトとは
AWS Lambdaには関数の最大実行時間に制限があります。デフォルトでは3秒、最大15分(900秒)に設定できます。この時間を超えると、Lambda関数は強制的に終了され、Task timed out after X.XX secondsというエラーが発生します。
タイムアウトが発生する主な原因は、データベースクエリの遅延、外部API呼び出しの待機時間、大量データの処理です。単にタイムアウト時間を延長するだけでなく、設計レベルでの改善が重要です。
タイムアウト時間の確認と設定変更
まずは現在の設定を確認し、必要に応じて調整する方法を確認しましょう。
AWSマネジメントコンソールでの確認
Lambda関数の詳細ページで「設定」→「全般設定」を開くと、現在のタイムアウト時間が表示されます。この値を増やすだけでは根本的な解決にはなりませんが、一時的な対応として有効です。
AWS CLIでの設定変更
# タイムアウト時間を600秒(10分)に設定
aws lambda update-function-configuration \
--function-name my-function \
--timeout 600
CloudFormationやTerraformを使用している場合も同様に設定可能です。
解決策1:非同期処理への切り替え
長時間かかる処理を別のLambda関数に委譲し、即座に呼び出し元に応答を返すパターンです。
SNSを経由した非同期実行
import boto3
import json
sns_client = boto3.client('sns')
def lambda_handler(event, context):
# 呼び出し元にはすぐに応答
# 長時間かかる処理は別のLambda関数に委譲
sns_client.publish(
TopicArn='arn:aws:sns:ap-northeast-1:123456789012:long-task-topic',
Message=json.dumps({
'user_id': event['user_id'],
'data': event['data']
})
)
return {
'statusCode': 202,
'body': json.dumps('Processing started in background')
}
この実装により、メイン関数はすぐに応答を返し、タイムアウトのリスクを軽減します。
SQSキューを使用したバッチ処理
import boto3
import json
sqs_client = boto3.client('sqs')
queue_url = 'https://sqs.ap-northeast-1.amazonaws.com/123456789012/long-task-queue'
def lambda_handler(event, context):
# タスクをキューに追加
for item in event['items']:
sqs_client.send_message(
QueueUrl=queue_url,
MessageBody=json.dumps({
'id': item['id'],
'timestamp': event['timestamp']
})
)
return {
'statusCode': 200,
'body': json.dumps(f"Added {len(event['items'])} items to queue")
}
# 別のLambda関数でキューから取得して処理
def process_queue_messages(event, context):
for record in event['Records']:
message_body = json.loads(record['body'])
# ここで長時間の処理を実行
print(f"Processing item: {message_body['id']}")
解決策2:処理の分割とバッチ化
大量のデータを一度に処理せず、小分けにして複数回のLambda実行に分散させる方法です。
S3への中間データ保存によるバッチ処理
import boto3
import json
s3_client = boto3.client('s3')
lambda_client = boto3.client('lambda')
def lambda_handler(event, context):
records = event['records'] # 1000件のデータ
# 100件ずつバッチに分割
batch_size = 100
for i in range(0, len(records), batch_size):
batch = records[i:i + batch_size]
batch_number = i // batch_size
# S3に一時保存
s3_client.put_object(
Bucket='temp-processing-bucket',
Key=f"batches/batch-{batch_number}.json",
Body=json.dumps(batch)
)
# 次のLambda関数を非同期で実行
lambda_client.invoke(
FunctionName='process-batch',
InvocationType='Event',
Payload=json.dumps({
'batch_number': batch_number,
'bucket': 'temp-processing-bucket'
})
)
return {
'statusCode': 200,
'body': json.dumps(f"Divided into {(len(records) + batch_size - 1) // batch_size} batches")
}
この方法により、各バッチは15分以内に処理完了できるようになります。
解決策3:Step Functions(ステートマシン)の活用
複数のLambda関数を組み合わせて長時間の処理フローを構築する際、Step Functionsが有効です。
Step Functions定義の例
{
"Comment": "長時間処理のワークフロー",
"StartAt": "データ準備",
"States": {
"データ準備": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:prepare-data",
"Next": "並列処理"
},
"並列処理": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "処理1",
"States": {
"処理1": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:process-part-1",
"End": true
}
}
},
{
"StartAt": "処理2",
"States": {
"処理2": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:process-part-2",
"End": true
}
}
}
],
"Next": "結果統合"
},
"結果統合": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-northeast-1:123456789012:function:aggregate-results",
"End": true
}
}
}
Step Functionsは個別のステップが15分以内で完了すれば、ワークフロー全体は数時間かかっても問題ありません。
ハマりやすいポイントと対処法
Cold Startによる予期しないタイムアウト
Lambda関数が一定時間使用されないと、コンテナが停止される「Cold Start」が発生します。再起動時の初期化処理に数秒かかり、制限時間を圧迫することがあります。
対策として、Provisioned Concurrencyを設定することで、Lambda関数を常時起動状態に保つことができます。ただしコスト増加につながるため、本当に必要な場合に限定してください。
外部API呼び出しのタイムアウト設定
import requests
import boto3
def lambda_handler(event, context):
# requestsのタイムアウトはLambdaのタイムアウトより短くする
try:
response = requests.get(
'https://api.example.com/data',
timeout=5 # Lambda全体の余裕を考慮
)
except requests.Timeout:
print("API call timed out")
# リトライまたは代替処理を実行
return {'statusCode': 503, 'body': 'Service temporarily unavailable'}
ネットワークI/Oの最適化
RDSやDynamoDBへのクエリが遅い場合、コネクション数の制限やクエリの最適化が必要です。特にコールドスタート直後は数秒のレイテンシが発生しやすいため、接続プーリングの導入も検討してください。
使うべき場面と使うべきでない場面
Lambda+タイムアウト対策が適切な場面
- APIリクエストの処理(数秒〜数分)
- イベント駆動の軽量な変換処理
- スケジュール実行による定期タスク
他のサービスを検討すべき場面
- 常時稼働が必要な長時間処理 → EC2やECS
- 数時間単位のバッチ処理 → AWS Batch
- 複雑なワークフロー → Step Functions + Lambda
実装時のベストプラクティス
タイムアウト対策を実装する際は、以下の点に注意してください。
- Lambda関数のタイムアウト値を、実際に必要な時間より30秒程度短く設定し、エラーハンドリングの時間を確保する
- CloudWatch Logsで実行時間を監視し、タイムアウト発生前に異常を検知するアラートを設定する
- 非同期処理を使う場合、DLQ(Dead Letter Queue)を設定して失敗したタスクを記録する
- 定期的に実行時間をレビューし、タイムアウト設定の妥当性を検証する
よくある質問
A: いいえ。AWS Lambdaの最大実行時間は15分(900秒)に固定されており、これを超える設定はできません。それ以上の処理時間が必要な場合は、処理を分割するか、EC2やECS、AWS Batchなど他のサービスの利用を検討してください。
A: Lambda関数が強制終了される時点での処理状態に依存します。データベースへの書き込みが完了していればそのまま保持され、DynamoDBのトランザクション中であれば自動的にロールバックされます。分散トランザクション対応が必要な場合は、冪等性(同じ処理を複数回実行しても結果が変わらない特性)の設計が重要です。
A: Step Functionsのワークフロー実行は1年間の有効期限がありますが、事実上は無制限です。各Lambda呼び出しは15分の制限を受けますが、ステップ間の待機時間は制限されません。ただし、Step Functionsの状態遷移数が多い場合、コストが増加することに注意してください。
まとめ
- AWS Lambdaのタイムアウトは最大15分に制限されており、超過すると関数は強制終了される
- 非同期処理(SNS/SQS)により、長時間の処理を別のLambda関数に委譲して対応できる
- 大量データはバッチに分割し、複数回のLambda実行に分散させることでタイムアウトを回避できる
- Step Functionsを使うことで、複数のLambda関数を組み合わせた長時間のワークフロー構築が可能
- Cold Start、外部API呼び出しなどのハマりポイントに注意し、実行時間を定期的に監視する必要がある
これらの対策を適切に組み合わせることで、AWS Lambda
おすすめAWSリソース
- AWS Documentation Detailed specs and best practices for every AWS service.
- AWS Skill Builder Free official learning platform. Great for certification prep.
- AWS Pricing Calculator Official tool for estimating costs before deployment.