Lỗi xảy ra
Log Lambda function của bạn hiển thị:
Task timed out after 3.00 seconds
Lambda đã buộc dừng function trước khi nó chạy xong. Timeout mặc định 3 giây hoạt động ổn với một function hello-world đơn giản. Nhưng chỉ cần thêm một lời gọi HTTP đến API bên thứ ba hoặc một truy vấn database dưới tải cao, 3 giây sẽ biến mất nhanh chóng.
Nguyên nhân gốc rễ
- Timeout mặc định quá ngắn — Lambda mặc định là 3 giây. Một lời gọi API chậm duy nhất là đủ để vượt qua giới hạn đó.
- Lời gọi mạng ra ngoài — Các request HTTP đến API bên thứ ba, RDS, hoặc DynamoDB có thể mất 1–5 giây khi tải cao, thậm chí lâu hơn.
- Độ trễ cold start — Các runtime dựa trên JVM (Java, Kotlin) thường tốn thêm 800ms–2s trước khi code của bạn bắt đầu chạy. Các package Python lớn có thể cộng thêm 200–400ms nữa.
- Vòng lặp vô hạn hoặc chờ đợi bị block — Một vòng lặp polling không bao giờ thoát, hoặc một lệnh
time.sleep(10)ẩn đâu đó trong call stack. - Mạng VPC — Các function chạy trong VPC khởi động chậm hơn và sẽ bị treo trên các lời gọi ra ngoài nếu không có NAT Gateway được cấu hình.
Bước 1 — Kiểm tra Log trước tiên
Chưa cần đụng vào cấu hình. Mở CloudWatch Logs để xem thời gian đang bị tiêu tốn ở đâu.
# Xem log theo thời gian thực qua AWS CLI
aws logs tail /aws/lambda/your-function-name --follow
# Hoặc lọc các dòng REPORT để xem thời gian thực thi
aws logs filter-log-events \
--log-group-name /aws/lambda/your-function-name \
--filter-pattern "REPORT" \
--query 'events[*].message' \
--output text
Dòng REPORT cung cấp toàn bộ thông tin bạn cần:
REPORT RequestId: abc-123 Duration: 2987.43 ms Billed Duration: 2988 ms Memory Size: 128 MB Max Memory Used: 67 MB Init Duration: 412.31 ms
Init Duration trên 400ms cho thấy vấn đề cold start. Duration gần sát giới hạn timeout có nghĩa là bản thân function thực sự chậm — và tăng timeout là giải pháp đúng đắn.
Bước 2 — Tăng Timeout
Tăng timeout trước. Giá trị tối đa là 15 phút (900 giây).
Qua AWS Console
- Vào Lambda → Function của bạn → Configuration → General configuration
- Nhấn Edit
- Đặt Timeout thành một giá trị hợp lý — 30 giây là điểm khởi đầu ổn cho các function thực hiện lời gọi ra ngoài
- Nhấn Save
Qua AWS CLI
aws lambda update-function-configuration \
--function-name your-function-name \
--timeout 30
Qua Serverless Framework (serverless.yml)
functions:
myFunction:
handler: handler.main
timeout: 30 # giây
Qua Terraform
resource "aws_lambda_function" "my_function" {
function_name = "my-function"
timeout = 30
# ... cấu hình khác
}
Quy tắc kinh nghiệm: đặt timeout bằng 2–3 lần thời gian thực thi tệ nhất dự kiến. Đừng vội đặt thẳng lên 900 — làm vậy sẽ che giấu các vấn đề hiệu năng thực sự.
Bước 3 — Thêm Log đo thời gian để xác định điểm nghẽn
Vẫn timeout ở 30 giây? Thêm instrumentation vào code để log cho bạn biết chính xác bước nào đang ngốn thời gian.
Python
import time
import logging
logger = logging.getLogger()
def handler(event, context):
t0 = time.time()
result = fetch_from_database()
logger.info(f"Truy vấn DB mất {time.time() - t0:.2f}s")
t1 = time.time()
response = call_external_api(result)
logger.info(f"Lời gọi API mất {time.time() - t1:.2f}s")
return response
Node.js
exports.handler = async (event) => {
console.time('db-query');
const result = await fetchFromDatabase();
console.timeEnd('db-query');
console.time('api-call');
const response = await callExternalAPI(result);
console.timeEnd('api-call');
return response;
};
Deploy, gọi thử một lần, rồi kiểm tra CloudWatch. Bước chậm sẽ hiện ra ngay lập tức.
Bước 4 — Tối ưu đoạn code chậm
Đặt timeout tường minh cho tất cả HTTP client
HTTP client không có timeout sẽ chờ mãi mãi. Hãy đặt timeout cho mọi lời gọi ra ngoài — không có ngoại lệ.
# Python với requests
import requests
response = requests.get('https://api.example.com/data', timeout=5) # tối đa 5 giây
# Python với httpx (async)
async with httpx.AsyncClient(timeout=5.0) as client:
response = await client.get('https://api.example.com/data')
// Node.js với axios
const axios = require('axios');
const response = await axios.get('https://api.example.com/data', {
timeout: 5000 // 5 giây tính bằng ms
});
Khởi tạo SDK client bên ngoài handler
AWS SDK client được tạo bên trong handler sẽ được khởi tạo lại mỗi lần gọi. Hãy chuyển chúng ra cấp module. Lambda tái sử dụng môi trường thực thi khi warm start, nên bạn chỉ trả chi phí khởi tạo đó đúng một lần.
# Sai — tạo client mới mỗi lần gọi
def handler(event, context):
dynamodb = boto3.client('dynamodb')
...
# Đúng — client được khởi tạo một lần, tái sử dụng khi warm start
import boto3
dynamodb = boto3.client('dynamodb')
def handler(event, context):
...
Tăng memory để có thêm CPU
CPU của Lambda tăng tuyến tính theo memory. Tăng từ 128MB lên 512MB cho bạn gấp 4 lần CPU. Với các workload nặng CPU, điều này có thể giảm thời gian thực thi xuống một nửa hoặc hơn.
aws lambda update-function-configuration \
--function-name your-function-name \
--memory-size 512
Chạy Lambda Power Tuning để tìm cấu hình memory cân bằng giữa tốc độ và chi phí cho function cụ thể của bạn.
Lambda trong VPC
Không có NAT Gateway, function của bạn đơn giản là không thể kết nối internet. Các lời gọi HTTP ra ngoài sẽ treo cho đến khi Lambda buộc dừng chúng. Kiểm tra route table của subnet — bạn cần một route cho 0.0.0.0/0 trỏ đến NAT Gateway (NAT Instance không đủ).
# Kiểm tra xem function có gắn với VPC không
aws lambda get-function-configuration \
--function-name your-function-name \
--query 'VpcConfig'
Bước 5 — Xác nhận đã sửa xong
Gọi trực tiếp function và kiểm tra kết quả trả về:
# Gọi thử đồng bộ
aws lambda invoke \
--function-name your-function-name \
--payload '{}' \
--cli-binary-format raw-in-base64-out \
output.json
cat output.json
Xem dòng REPORT trong CloudWatch. Duration thấp hơn nhiều so với giới hạn timeout là bạn đã xong:
REPORT RequestId: xyz-456 Duration: 1243.12 ms Billed Duration: 1244 ms
Không còn Task timed out after 3.00 seconds trong log nữa. Đã sửa xong.
Bài học rút ra
- 3 giây là mặc định của Lambda, không phải khuyến nghị. Hầu hết các function production cần 15–60 giây.
- Đặt timeout cho mọi function thực hiện lời gọi ra ngoài — và chọn con số đó một cách có chủ đích, không phải để mặc định.
- Cold start của Java và Kotlin thường ngốn 1–2 giây trước khi handler của bạn chạy. Nếu điều đó không chấp nhận được, hãy xem xét Provisioned Concurrency hoặc SnapStart (Java 11+).
- Đặt timeout của HTTP client ngắn hơn timeout của Lambda. Như vậy bạn sẽ nhận được exception có thể xử lý được — thay vì phải chờ Lambda buộc dừng toàn bộ function.

