Ngôn ngữ hiển thị:
Nếu bạn đang chạy Lambda ở production và chưa từng gặp cold start, có hai khả năng: hoặc traffic của bạn quá đều, hoặc bạn chưa nhìn vào log kỹ. Cold start không phải bug — đó là đặc tính thiết kế của kiến trúc serverless. Nhưng "đặc tính" không có nghĩa là phải chấp nhận nó.
Lambda hoạt động theo mô hình "pay per invocation" — khi không có request, không có container nào đang chờ. Khi request đến, AWS phải: cấp phát micro-VM, tải runtime (Node, Python, Java...), giải nén deployment package, khởi tạo Lambda execution environment, rồi mới chạy code của bạn. Chuỗi bước này — cold start — chiếm từ vài trăm milliseconds đến vài giây, tùy runtime và package size.
Với Java hay .NET, con số này có thể lên đến 5-8 giây vì JVM cần warm up. Node.js hay Python thường nhẹ hơn, khoảng 200-800ms. Nhưng khi bạn đang build API cần P99 dưới 500ms, ngay cả 200ms extra cũng là vấn đề nghiêm trọng.
Khổ nỗi là cold start không xảy ra theo pattern có thể predict được. Nó xuất hiện khi: function idle quá 5-15 phút, traffic tăng đột biến vượt số instance đang warm, deploy phiên bản mới, hay AWS thu hồi execution environment vì lý do nội bộ. Tức là bất cứ lúc nào.
Provisioned Concurrency (PC) là cách trực tiếp nhất: bạn trả tiền để AWS giữ sẵn N execution environment ở trạng thái warm, sẵn sàng xử lý request mà không cần init time. Khai báo đơn giản:
aws lambda put-provisioned-concurrency-config --function-name my-api --qualifier production --provisioned-concurrent-executions 10PC phù hợp nhất với các endpoint critical — login API, checkout flow, hay bất kỳ user-facing path nào mà latency ảnh hưởng trực tiếp đến conversion. Đừng áp dụng cho toàn bộ function stack; chỉ những Lambda nằm trên critical path.
Một trick hay là kết hợp PC với Application Auto Scaling để scale up PC trước giờ cao điểm và scale down khi traffic giảm — vừa đảm bảo performance, vừa kiểm soát chi phí:
aws application-autoscaling register-scalable-target --service-namespace lambda --resource-id function:my-api:production --scalable-dimension lambda:function:ProvisionedConcurrency --min-capacity 2 --max-capacity 20Nếu stack của bạn dùng Java 11+ với Corretto runtime, SnapStart là tính năng không thể bỏ qua. Thay vì khởi tạo JVM mỗi lần cold start, AWS snapshot trạng thái initialized của execution environment và restore từ snapshot — thời gian giảm từ vài giây xuống dưới 1 giây, đôi khi dưới 200ms.
Enable SnapStart khi tạo hoặc update function:
aws lambda update-function-configuration --function-name my-java-api --snap-start ApplyOn=PublishedVersionsLưu ý quan trọng: SnapStart hoạt động với published version, không phải $LATEST. Bạn cần publish version sau mỗi deploy:
aws lambda publish-version --function-name my-java-apiMột điểm cần chú ý khi dùng SnapStart: nếu code của bạn trong init phase tạo connection đến database hay external service, connection đó có thể bị invalidate sau khi restore từ snapshot. Implement CRaC (Coordinated Restore at Checkpoint) interface để handle gracefully — reinitialize connections trong afterRestore() hook.
Cold start time tỷ lệ thuận với deployment package size. Một package 50MB sẽ cold start chậm hơn đáng kể so với 5MB. Vài nguyên tắc cơ bản:
Với Node.js: dùng webpack hoặc esbuild để bundle và tree-shake, loại bỏ toàn bộ node_modules không cần thiết. Đừng bundle aws-sdk — runtime đã có sẵn. Package size target: dưới 5MB cho function thông thường.
Với Python: dùng Lambda Layers cho dependencies dùng chung. Package chỉ chứa application code, không kéo toàn bộ site-packages vào zip.
Với Java: dùng GraalVM Native Image hoặc Quarkus với Lambda extension để compile native — startup time từ vài giây xuống dưới 100ms. Chi phí build pipeline cao hơn nhưng production performance xứng đáng.
Về memory: đây là trade-off thú vị. Lambda phân bổ CPU tỷ lệ thuận với memory. Tăng memory từ 512MB lên 1024MB không chỉ cho thêm RAM — bạn còn được thêm CPU, giúp init phase chạy nhanh hơn. Dùng AWS Lambda Power Tuning để tìm sweet spot giữa cost và performance.
Warm-up pings: Dùng CloudWatch Events rule ping function mỗi 5 phút với một event đặc biệt (ví dụ {"ping": true}) — function detect và return sớm mà không xử lý logic. Cách này free và hiệu quả cho traffic thấp, nhưng không scale tốt khi cần nhiều concurrent warm instances.
Lazy initialization: Đẩy toàn bộ heavy initialization (DB connection pool, SDK client, config loading) ra ngoài handler — ở module level, chạy một lần khi container warm. Điều này không giảm cold start time mà giúp warm invocations nhanh hơn và tránh init lại giữa các request.
// Node.js - đặt ngoài handler
const dbClient = new DatabaseClient(process.env.DB_URL);
const s3Client = new S3Client({ region: 'ap-northeast-1' });
export const handler = async (event) => {
// dbClient và s3Client đã sẵn sàng, không init lại
const result = await dbClient.query('SELECT...');
return result;
};Lambda URLs thay API Gateway: Nếu bạn không cần tính năng advanced của API Gateway (auth, throttling, usage plan), dùng Lambda Function URLs thay thế — loại bỏ một hop latency.
Q: Provisioned Concurrency có đắt không? Có cách nào rẻ hơn không?A: PC tính phí theo số concurrency × thời gian giữ warm, riêng biệt với invocation cost. Đắt hơn on-demand nhưng rẻ hơn chạy EC2 để warm. Nếu budget eo hẹp, warm-up ping kết hợp với lazy init là combo free khá hiệu quả cho traffic dưới 10 req/min.
Q: SnapStart có hoạt động với tất cả Java framework không?A: SnapStart tương thích với Java 11+ Corretto runtime. Spring Boot hoạt động nhưng cần cẩn thận với bean initialization — một số bean tạo connection hoặc cache tại startup cần implement CRaC hooks. Quarkus và Micronaut có hỗ trợ tốt hơn out-of-the-box.
Q: Tăng memory có luôn giảm cold start không?A: Không phải luôn luôn. Với Python và Node.js, tăng từ 256MB lên 512MB thường thấy cải thiện đáng kể vì CPU tăng theo. Từ 1024MB trở lên, diminishing return rõ rệt — cold start không giảm nhiều nhưng chi phí mỗi invocation tăng. Chạy Power Tuning để có số liệu cụ thể cho function của bạn.
Không có silver bullet cho cold start. Provisioned Concurrency hiệu quả nhất nhưng tốn tiền — dùng cho critical path. SnapStart dành cho Java team và gần như là must-have. Tối ưu package size là baseline mọi project đều nên làm từ đầu, không tốn chi phí runtime. Warm-up ping phù hợp cho function không critical với traffic thưa.
Nói thật thì phần lớn cold start problem bắt nguồn từ hai nguyên nhân: package quá nặng và Java runtime không được configure đúng. Giải quyết hai điểm đó trước, sau đó đo lại với X-Ray trước khi quyết định bỏ tiền vào Provisioned Concurrency. Tối ưu có căn cứ bao giờ cũng tốt hơn tối ưu theo cảm tính.