Lambda ngoài VPC chạy ngon, nhưng gắn vào VPC để gọi RDS thì cold start từ 200ms lên 5s. Bài này là những gì cần biết để Lambda chạy production: VPC, concurrency, và Powertools.


  flowchart TB
    subgraph VPC["VPC"]
        Lambda["Lambda VPC-attached<br/>ENI trong private subnet"]
        RDS["RDS PostgreSQL"]
        Lambda -->|"port 5432"| RDS
    end
    subgraph Concurrency
        Prov["Provisioned: 10 instances always warm<br/>$0.015/GB-hr phụ phí (thêm vào execution cost,<br/>không thay thế on-demand — tổng cost cao hơn)"]
        Res["Reserved: 50 slots guaranteed<br/>Free · bảo vệ khỏi function khác"]
        OnDemand["On-Demand: 1,000 limit<br/>Can be throttled"]
    end

Lambda trong VPC

aws lambda update-function-configuration \
  --function-name api-handler \
  --vpc-config SubnetIds=subnet-private-a,subnet-private-b,SecurityGroupIds=sg-lambda

Hậu quả: cold start chậm thêm 2-5s (tạo ENI trong subnet), mất internet access. Giải pháp cho S3/DynamoDB: VPC Gateway Endpoint (miễn phí giờ, nhưng có phí xử lý data ~$0.01/GB). Cho Secrets Manager/SQS: Interface Endpoint (~$7.20/tháng/AZ).


Concurrency: Reserved vs Provisioned

# Reserved: đảm bảo 50 slot cho function này (miễn phí)
aws lambda put-function-concurrency --function-name api-handler --reserved-concurrent-executions 50

# Provisioned: pre-warm 10 instances (loại bỏ cold start)
# Lưu ý: cần publish version trước, không dùng $LATEST
aws lambda publish-version --function-name api-handler
aws lambda put-provisioned-concurrency-config \
  --function-name api-handler --qualifier '1' \
  --provisioned-concurrent-executions 10
LoạiCostDùng khi
ReservedMiễn phíBảo vệ function A không đói khi B spike
Provisioned$0.015/GB-hrProduction API cần sub-100ms p99

Powertools: structured logging + metrics + tracing

import { Logger, injectLambdaContext } from "@aws-lambda-powertools/logger";
import { Metrics, logMetrics } from "@aws-lambda-powertools/metrics";
import { Tracer, captureLambdaHandler } from "@aws-lambda-powertools/tracer";
import middy from "@middy/core";

const logger = new Logger({ serviceName: "api-handler" });
const metrics = new Metrics({ namespace: "MyApp" });
const tracer = new Tracer({ serviceName: "api-handler" });

const handler = async (event: any) => {
  logger.info("Processing", { path: event.path });
  metrics.addMetric("SuccessfulRequest", "Count", 1);

  const segment = tracer.getSegment()!;
  const sub = segment.addNewSubsegment("## dbQuery");
  const result = await db.query("...");
  sub.close();

  return { statusCode: 200, body: JSON.stringify(result) };
};

export const main = middy(handler)
  .use(injectLambdaContext(logger))
  .use(logMetrics(metrics))
  .use(captureLambdaHandler(tracer));
  • Logger: structured JSON + correlation ID (context.awsRequestId), cold start marker
  • Metrics: EMF → CloudWatch metrics, không cần PutMetricData API call (không throttle, không cost thêm)
  • Tracer: X-Ray subsegment tự động cho DynamoDB, S3, HTTP calls

Những nguyên tắc nhớ nhanh

  • VPC-attached Lambda: chỉ khi cần truy cập tài nguyên private (RDS, ElastiCache, Secrets Manager, on-premise qua Direct Connect/VPN). Dùng VPC Endpoint thay NAT Gateway
  • Provisioned concurrency: loại bỏ cold start. Application Auto Scaling cho scheduled scaling
  • Powertools: Logger + Metrics + Tracer — dùng ngay từ function đầu tiên

Bài sau: Phần 12: RDS & Aurora PostgreSQL — managed SQL toàn tập