Giới Thiệu: Serverless Không Có Nghĩa Là Miễn Phí
Serverless nghe thì tuyệt vời lắm — "chỉ trả tiền cho những gì bạn dùng". Nhiều team nghe vậy là chuyển ồ ạt workload sang AWS Lambda, Azure Functions, Google Cloud Functions mà không nghĩ nhiều. Nhưng nói thật, thực tế phũ phàng hơn nhiều. Nếu không tối ưu đúng cách, hóa đơn serverless có thể phình to gấp 3 lần so với dự kiến.
Theo nghiên cứu của Deloitte với các khách hàng Fortune 100, serverless có thể tiết kiệm đến 57% chi phí so với kiến trúc server truyền thống. Nghe hấp dẫn đúng không? Nhưng đó là khi bạn biết cách tối ưu.
Ngược lại, mình từng chứng kiến một team xử lý dữ liệu chi hơn 10.000 USD/tháng cho 80 job ETL trên AWS Glue — chỉ vì billing tính cả thời gian idle. Sau khi chuyển sang Apache Airflow trên EC2 Spot Instances, chi phí giảm xuống còn khoảng 400 USD. Giảm 96%. Con số đó không phải gõ nhầm đâu.
Trong bài viết này, mình sẽ hướng dẫn bạn từ A đến Z cách tối ưu chi phí serverless trên cả ba nền tảng cloud lớn nhất. Tất cả đi kèm code minh họa, công cụ thực tế và chiến lược áp dụng ngay được. Nào, bắt đầu thôi.
1. Hiểu Rõ Cấu Trúc Chi Phí Serverless Trên Từng Nền Tảng
1.1 AWS Lambda — Mô Hình Tính Phí Theo GB-Second
AWS Lambda tính phí dựa trên ba yếu tố chính:
- Số lần gọi (Invocations): 0.20 USD cho mỗi 1 triệu request. 1 triệu request đầu tiên miễn phí mỗi tháng — nghe nhiều nhưng một API bận rộn xài hết rất nhanh.
- Thời gian thực thi (Duration): Tính theo đơn vị GB-second — bộ nhớ được cấp (GB) nhân với thời gian chạy (giây). Đây là phần "ngốn" tiền nhất.
- Bộ nhớ được cấp (Memory): Từ 128 MB đến 10.240 MB. Điều nhiều người không biết là bộ nhớ không chỉ ảnh hưởng đến RAM — nó còn quyết định lượng vCPU mà function nhận được.
Bẫy chi phí cần biết: Một function cấu hình 1.024 MB chạy trong 500ms tiêu tốn 0,5 GB-second mỗi lần gọi. Free tier 400.000 GB-second nghe có vẻ nhiều, nhưng thực tế chỉ đủ cho khoảng 800.000 lần gọi. Một API bận rộn có thể dùng hết trong 24 giờ. Đúng rồi, chỉ một ngày.
1.2 Azure Functions — Linh Hoạt Với Ba Gói Hosting
Azure Functions cho bạn ba lựa chọn hosting, và chọn sai có thể tốn tiền oan:
- Consumption Plan: Serverless thuần túy — chỉ trả tiền khi function chạy. Tự động scale nhưng có thể gặp cold start.
- Premium Plan: Có pre-warmed instances giúp loại bỏ cold start, hỗ trợ VNET integration và thời gian thực thi dài hơn. Tuy nhiên, bạn trả tiền dù có dùng hay không — giống reserved infrastructure hơn là serverless.
- Dedicated Plan: Chạy trên App Service Plan riêng, phù hợp khi bạn đã có infrastructure sẵn.
Sai lầm phổ biến nhất? Chọn Premium Plan quá sớm. Nó cải thiện cold start thật, nhưng về bản chất nó hoạt động giống reserved infrastructure — bạn trả tiền dù function nằm im không làm gì.
1.3 Google Cloud Functions — Chi Phí Networking Ẩn
Google Cloud Functions (thế hệ 2, chạy trên Cloud Run) tính phí theo:
- Invocations: Số lần gọi function.
- CPU và Memory: Tính riêng biệt, cho phép cấu hình độc lập — điểm này linh hoạt hơn AWS.
- Networking: Đây là phần hay bị bỏ qua. Chi phí truyền dữ liệu cross-region và outbound có thể trở thành khoản chi phí "khủng" nếu kiến trúc không được tối ưu.
Điểm sáng: Cloud Functions thế hệ 2 có cold start rất ấn tượng — function Python và Node.js thường khởi động trong dưới 200ms. Minimum instances cũng đơn giản hơn nhiều so với Provisioned Concurrency bên AWS.
2. Right-Sizing Memory — Chiến Lược Giảm Chi Phí Nhanh Nhất
2.1 Tại Sao Right-Sizing Quan Trọng Đến Vậy?
Right-sizing bộ nhớ là cách đơn giản nhất và hiệu quả nhất để giảm chi phí serverless. Và có một quy tắc nghe rất phản trực giác: tăng bộ nhớ có thể làm giảm chi phí tổng thể.
Sao lại thế? Khi bạn tăng bộ nhớ trên AWS Lambda, vCPU cũng tăng theo. Function có 2.048 MB chạy nhanh gấp đôi function 1.024 MB — nhưng chi phí mỗi giây chỉ gấp đôi. Nếu function kết thúc nhanh hơn 2 lần, tổng chi phí không đổi. Và trong nhiều trường hợp, function chạy nhanh hơn nhiều hơn 2 lần nhờ hiệu ứng CPU-bound, dẫn đến chi phí thấp hơn.
Nói cách khác, đôi khi trả nhiều tiền hơn cho mỗi giây lại khiến bạn trả ít tiền hơn tổng thể. Nghe lạ nhưng đúng.
2.2 Dùng AWS Lambda Power Tuning — Hướng Dẫn Từng Bước
AWS Lambda Power Tuning là công cụ mã nguồn mở chạy trên AWS Step Functions. Nó giúp bạn tìm cấu hình bộ nhớ tối ưu cho mỗi function với ba chiến lược: cost (tiết kiệm nhất), speed (nhanh nhất), và balanced (cân bằng).
Bước 1: Triển khai công cụ
Cách nhanh nhất là dùng AWS SAR:
# Triển khai bằng AWS SAM CLI
sam init --location https://github.com/alexcasalboni/aws-lambda-power-tuning
cd aws-lambda-power-tuning
sam build
sam deploy -g
# Hoặc triển khai trực tiếp từ SAR qua AWS CLI
aws serverlessrepo create-cloud-formation-change-set \
--application-id arn:aws:serverlessrepo:us-east-1:451282441545:applications/aws-lambda-power-tuning \
--stack-name lambda-power-tuning \
--capabilities CAPABILITY_IAM
Bước 2: Chạy State Machine
# Tạo file input cho Power Tuning
{
"lambdaARN": "arn:aws:lambda:ap-southeast-1:123456789:function:my-api-handler",
"powerValues": [128, 256, 512, 1024, 1536, 2048, 3008],
"num": 50,
"payload": "{\"httpMethod\": \"GET\", \"path\": \"/api/products\"}",
"parallelInvocation": true,
"strategy": "cost"
}
# Lấy ARN của State Machine
STATE_MACHINE_ARN=$(aws stepfunctions list-state-machines \
--query "stateMachines[?contains(name, 'powerTuningStateMachine')].stateMachineArn" \
--output text)
# Chạy Power Tuning
aws stepfunctions start-execution \
--state-machine-arn "$STATE_MACHINE_ARN" \
--input file://power-tuning-input.json
Bước 3: Xem kết quả và áp dụng
# Lấy kết quả execution
EXECUTION_ARN="arn:aws:states:ap-southeast-1:123456789:execution:powerTuning:test-1"
aws stepfunctions describe-execution \
--execution-arn "$EXECUTION_ARN" \
--query "output" \
--output text | python3 -m json.tool
# Output mẫu:
# {
# "power": 1024,
# "cost": 0.0000025,
# "duration": 45.3,
# "stateMachine": {
# "executionCost": 0.00045,
# "lambdaCost": 0.12345,
# "visualization": "https://lambda-power-tuning.show/#..."
# }
# }
# Áp dụng cấu hình tối ưu
aws lambda update-function-configuration \
--function-name my-api-handler \
--memory-size 1024
Trong thực tế, mình thấy nhiều trường hợp chuyển từ 128 MB lên 1.024 MB giảm thời gian chạy 75%, và chi phí tổng giảm 40% dù bộ nhớ tăng gấp 8 lần. Kết quả này không hiếm chút nào.
2.3 Script Tự Động Quét Function Chưa Được Tối Ưu
Đây là script Python mình hay dùng để tự động phát hiện các Lambda function có dấu hiệu chưa được tối ưu memory. Nó sẽ quét toàn bộ functions trong region và highlight những function đang "lãng phí" tài nguyên:
import boto3
from datetime import datetime, timedelta
def find_unoptimized_lambda_functions(region='ap-southeast-1'):
"""
Tim cac Lambda function co dau hieu chua toi uu memory:
- Memory su dung thuc te < 50% memory duoc cap
- Duration cao bat thuong so voi memory thap
"""
lambda_client = boto3.client('lambda', region_name=region)
cloudwatch = boto3.client('cloudwatch', region_name=region)
paginator = lambda_client.get_paginator('list_functions')
results = []
for page in paginator.paginate():
for func in page['Functions']:
func_name = func['FunctionName']
memory_mb = func['MemorySize']
end_time = datetime.utcnow()
start_time = end_time - timedelta(days=14)
try:
mem_stats = cloudwatch.get_metric_statistics(
Namespace='AWS/Lambda',
MetricName='MaxMemoryUsed',
Dimensions=[
{'Name': 'FunctionName', 'Value': func_name}
],
StartTime=start_time,
EndTime=end_time,
Period=86400,
Statistics=['Maximum']
)
duration_stats = cloudwatch.get_metric_statistics(
Namespace='AWS/Lambda',
MetricName='Duration',
Dimensions=[
{'Name': 'FunctionName', 'Value': func_name}
],
StartTime=start_time,
EndTime=end_time,
Period=86400,
Statistics=['Average', 'Maximum']
)
invocation_stats = cloudwatch.get_metric_statistics(
Namespace='AWS/Lambda',
MetricName='Invocations',
Dimensions=[
{'Name': 'FunctionName', 'Value': func_name}
],
StartTime=start_time,
EndTime=end_time,
Period=1209600,
Statistics=['Sum']
)
if not mem_stats['Datapoints'] or not invocation_stats['Datapoints']:
continue
max_mem_used = max(d['Maximum'] for d in mem_stats['Datapoints'])
avg_duration = sum(d['Average'] for d in duration_stats['Datapoints']) / len(duration_stats['Datapoints'])
total_invocations = sum(d['Sum'] for d in invocation_stats['Datapoints'])
mem_utilization = (max_mem_used / memory_mb) * 100
if mem_utilization < 50 and total_invocations > 1000:
estimated_monthly_savings = (
(memory_mb - max_mem_used * 1.2) / 1024
* avg_duration / 1000
* total_invocations / 14 * 30
* 0.0000166667
)
results.append({
'function_name': func_name,
'current_memory_mb': memory_mb,
'max_memory_used_mb': round(max_mem_used),
'memory_utilization': f"{mem_utilization:.1f}%",
'avg_duration_ms': round(avg_duration, 1),
'monthly_invocations': round(total_invocations / 14 * 30),
'estimated_monthly_savings_usd': round(estimated_monthly_savings, 2),
'recommendation': f"Giam memory xuong {int(max_mem_used * 1.3)}MB"
})
except Exception as e:
continue
results.sort(key=lambda x: x['estimated_monthly_savings_usd'], reverse=True)
return results
if __name__ == '__main__':
unoptimized = find_unoptimized_lambda_functions()
for func in unoptimized:
print(f" {func['function_name']}: "
f"Memory {func['current_memory_mb']}MB -> dung thuc te {func['max_memory_used_mb']}MB "
f"({func['memory_utilization']}), "
f"Tiet kiem uoc tinh: ${func['estimated_monthly_savings_usd']}/thang")
3. Chuyển Sang ARM/Graviton — Giảm Ngay 20% Chi Phí
3.1 Tại Sao ARM Rẻ Hơn Và Nhanh Hơn?
AWS Lambda hỗ trợ bộ xử lý ARM-based Graviton2 từ tháng 9/2021. Graviton2 mang lại hiệu năng cao hơn 19% với chi phí thấp hơn 20% so với x86. Kết hợp cả hai yếu tố, bạn tiết kiệm kha khá mà gần như không cần thay đổi code.
Chuyển đổi cực kỳ đơn giản — chỉ một dòng lệnh:
# Chuyển Lambda function sang ARM/Graviton2
aws lambda update-function-configuration \
--function-name my-api-handler \
--architectures arm64
# Hoac trong CloudFormation/SAM template
# Resources:
# MyFunction:
# Type: AWS::Serverless::Function
# Properties:
# Architectures:
# - arm64
# Runtime: python3.12
# Handler: app.lambda_handler
Lưu ý nhỏ: Hầu hết các runtime phổ biến (Python, Node.js, Java, .NET) đều hỗ trợ ARM mà không cần sửa code. Tuy nhiên, nếu function dùng native compiled dependencies — kiểu một số thư viện C/C++ — thì bạn cần build lại cho kiến trúc ARM.
3.2 Script Chuyển Đổi Hàng Loạt Sang ARM
Nếu bạn có nhiều functions cần chuyển, đây là script bash giúp tự động hóa quá trình:
#!/bin/bash
# Script chuyen doi tat ca Lambda functions sang ARM/Graviton2
# Chi ap dung cho cac function dang dung x86_64
REGION="ap-southeast-1"
DRY_RUN=true # Dat false de thuc thi that
echo "=== Quet Lambda functions dang dung x86_64 ==="
FUNCTIONS=$(aws lambda list-functions \
--region $REGION \
--query "Functions[?Architectures[0]=='x86_64'].FunctionName" \
--output text)
COUNT=0
for FUNC_NAME in $FUNCTIONS; do
RUNTIME=$(aws lambda get-function-configuration \
--function-name "$FUNC_NAME" \
--region $REGION \
--query "Runtime" \
--output text)
case $RUNTIME in
python3.*|nodejs*|java*|dotnet*)
COUNT=$((COUNT + 1))
if [ "$DRY_RUN" = true ]; then
echo "[DRY RUN] $FUNC_NAME ($RUNTIME) -> arm64"
else
aws lambda update-function-configuration \
--function-name "$FUNC_NAME" \
--architectures arm64 \
--region $REGION
echo "[DONE] $FUNC_NAME ($RUNTIME) -> arm64"
fi
;;
*)
echo "[SKIP] $FUNC_NAME ($RUNTIME) - Runtime khong ho tro ARM"
;;
esac
done
echo "=== Tong: $COUNT functions co the chuyen sang ARM ==="
echo "=== Tiet kiem uoc tinh: 20% chi phi compute ==="
4. Tối Ưu Event Routing Và Batching
4.1 Sức Mạnh Của Event Filtering
Đây là điều mà nhiều team bỏ qua: mỗi lần Lambda function được gọi, bạn đều mất tiền — kể cả khi function chỉ kiểm tra điều kiện rồi return luôn. Event filtering cho phép bạn lọc events trước khi function được gọi, cắt giảm đáng kể số invocations vô ích.
# Vi du: Chi trigger Lambda khi co don hang gia tri cao tren SQS
# CloudFormation/SAM template
Resources:
OrderProcessorFunction:
Type: AWS::Serverless::Function
Properties:
Handler: order_processor.handler
Runtime: python3.12
Architectures:
- arm64
Events:
SQSEvent:
Type: SQS
Properties:
Queue: !GetAtt OrderQueue.Arn
BatchSize: 100
MaximumBatchingWindowInSeconds: 30
FilterCriteria:
Filters:
- Pattern: '{"body": {"orderTotal": [{"numeric": [">=", 100]}]}}'
Tác động chi phí: Xử lý 100 records trong một lần gọi 2 giây rẻ hơn rất nhiều so với 100 lần gọi riêng biệt mỗi lần 100ms. Mỗi invocation đều có overhead khởi tạo, và cái overhead đó cộng dồn nhanh lắm.
4.2 Tránh NAT Gateway — Kẻ Giết Chi Phí Thầm Lặng
Cái này mình phải nhấn mạnh vì quá nhiều người mắc phải. Nếu Lambda function nằm trong VPC và cần truy cập dịch vụ AWS như S3 hoặc DynamoDB, traffic sẽ đi qua NAT Gateway. Chi phí NAT Gateway có thể âm thầm gấp đôi hóa đơn serverless của bạn mà bạn không hề hay biết.
Giải pháp? VPC Endpoints. Đơn giản mà hiệu quả:
# Tao VPC Endpoint cho S3 (Gateway type - mien phi)
aws ec2 create-vpc-endpoint \
--vpc-id vpc-abc123 \
--service-name com.amazonaws.ap-southeast-1.s3 \
--route-table-ids rtb-abc123
# Tao VPC Endpoint cho DynamoDB (Gateway type - mien phi)
aws ec2 create-vpc-endpoint \
--vpc-id vpc-abc123 \
--service-name com.amazonaws.ap-southeast-1.dynamodb \
--route-table-ids rtb-abc123
# Tao VPC Endpoint cho SQS (Interface type - co phi nho nhung re hon NAT)
aws ec2 create-vpc-endpoint \
--vpc-id vpc-abc123 \
--vpc-endpoint-type Interface \
--service-name com.amazonaws.ap-southeast-1.sqs \
--subnet-ids subnet-abc123 \
--security-group-ids sg-abc123
5. Kiểm Soát Concurrency Và Cold Start Thông Minh
5.1 Reserved Concurrency — Ngăn Chặn Hóa Đơn Bất Ngờ
Tự động scale là lợi thế lớn của serverless, nhưng cũng là con dao hai lưỡi. Thật đấy. Một bug gây recursive invocation hoặc traffic spike bất thường có thể khiến Lambda scale lên hàng ngàn concurrent executions, tạo ra hóa đơn khổng lồ chỉ trong vài phút.
# Dat reserved concurrency de gioi han so lan chay dong thoi
aws lambda put-function-concurrency \
--function-name my-api-handler \
--reserved-concurrent-executions 100
# Neu phat hien recursive invocation, dat concurrency = 0 de dung ngay
aws lambda put-function-concurrency \
--function-name runaway-function \
--reserved-concurrent-executions 0
5.2 Provisioned Concurrency — Chỉ Dùng Khi Thật Sự Cần
Provisioned Concurrency loại bỏ cold start hoàn toàn — nhưng đánh đổi bằng chi phí cố định. Bạn trả tiền cho mỗi instance được provisioned dù có request hay không. Theo kinh nghiệm, chỉ nên dùng cho các function có yêu cầu latency nghiêm ngặt (dưới 100ms).
# Cau hinh Provisioned Concurrency voi Auto Scaling
# Tao alias
aws lambda create-alias \
--function-name my-api-handler \
--name prod \
--function-version 5
# Dat Provisioned Concurrency
aws lambda put-provisioned-concurrency-config \
--function-name my-api-handler \
--qualifier prod \
--provisioned-concurrent-executions 10
# Them Auto Scaling de tu dong dieu chinh theo traffic
aws application-autoscaling register-scalable-target \
--service-namespace lambda \
--resource-id "function:my-api-handler:prod" \
--scalable-dimension "lambda:function:ProvisionedConcurrency" \
--min-capacity 5 \
--max-capacity 50
aws application-autoscaling put-scaling-policy \
--service-namespace lambda \
--resource-id "function:my-api-handler:prod" \
--scalable-dimension "lambda:function:ProvisionedConcurrency" \
--policy-name lambda-target-tracking \
--policy-type TargetTrackingScaling \
--target-tracking-scaling-policy-configuration '{
"TargetValue": 0.7,
"PredefinedMetricSpecification": {
"PredefinedMetricType": "LambdaProvisionedConcurrencyUtilization"
}
}'
6. Tối Ưu Trên Azure Functions Và Google Cloud Functions
6.1 Azure Functions — Chọn Đúng Hosting Plan
Sai lầm tốn kém nhất trên Azure là chọn Premium Plan khi Consumption Plan đã đủ dùng. Vậy chọn thế nào cho đúng?
- Dùng Consumption Plan khi: Function chạy dưới 5 phút, cold start 1-2 giây chấp nhận được, và traffic không đều.
- Dùng Premium Plan khi: Cần VNET integration, function chạy lâu hơn 5 phút, hoặc latency yêu cầu dưới 200ms.
Nếu không chắc chắn, hãy bắt đầu với Consumption Plan rồi upgrade sau nếu cần. Đừng bao giờ làm ngược lại.
Kiểm tra chi phí thực tế trên Azure:
# Azure CLI - Kiem tra chi phi Function App trong 30 ngay qua
az consumption usage list \
--start-date 2026-02-01 \
--end-date 2026-03-01 \
--query "[?contains(instanceName, 'my-function-app')].{
Date: usageStart,
Quantity: quantity,
Cost: pretaxCost,
Meter: meterDetails.meterName
}" \
--output table
# Kiem tra execution count va duration
az monitor metrics list \
--resource "/subscriptions/{sub-id}/resourceGroups/{rg}/providers/Microsoft.Web/sites/{app-name}" \
--metric "FunctionExecutionCount,FunctionExecutionUnits" \
--interval PT1H \
--start-time 2026-03-01T00:00:00Z \
--end-time 2026-03-09T00:00:00Z
Một điều nữa về Durable Functions: Nếu bạn dùng Azure Durable Functions cho orchestration, cẩn thận với chuỗi orchestration dài. Chúng tăng thời gian thực thi và tương tác storage một cách khó lường, âm thầm đẩy chi phí lên cao mà bạn không nhận ra cho đến khi nhìn hóa đơn.
6.2 Google Cloud Functions — Kiểm Soát Networking Cost
Trên Google Cloud, chi phí networking thường bị đánh giá thấp. Mình thấy nhiều team bất ngờ khi networking cost chiếm tỷ trọng lớn hơn cả compute. Để tối ưu:
- Giữ services trong cùng region: Cross-region communication có thể là thành phần billing lớn nhất mà bạn không ngờ tới.
- Giảm API chatter: Gom nhiều request nhỏ thành một batch request thay vì gọi riêng lẻ.
- Dùng minimum instances: Google Cloud Functions thế hệ 2 hỗ trợ minimum instances — đơn giản hơn và thường rẻ hơn Provisioned Concurrency bên AWS.
# Deploy Google Cloud Function the he 2 voi cau hinh toi uu
gcloud functions deploy my-api-handler \
--gen2 \
--runtime=python312 \
--region=asia-southeast1 \
--memory=256Mi \
--cpu=0.167 \
--timeout=60s \
--min-instances=1 \
--max-instances=100 \
--trigger-http \
--allow-unauthenticated
# Kiem tra chi phi qua BigQuery billing export
bq query --use_legacy_sql=false '
SELECT
labels.value AS function_name,
SUM(cost) AS total_cost,
SUM(usage.amount) AS total_usage,
usage.unit
FROM `project.dataset.gcp_billing_export_v1_XXXXX`
LEFT JOIN UNNEST(labels) AS labels
ON labels.key = "cloudfunctions.googleapis.com/function_name"
WHERE service.description = "Cloud Functions"
AND invoice.month = "202603"
GROUP BY function_name, usage.unit
ORDER BY total_cost DESC
LIMIT 10
'
7. Compute Savings Plans Cho Serverless
7.1 AWS Compute Savings Plans Áp Dụng Cho Lambda
Đây là điều khá nhiều người không biết: AWS Compute Savings Plans cũng áp dụng cho Lambda, không chỉ EC2 và Fargate. Bạn có thể tiết kiệm thêm 17% chi phí Lambda chỉ bằng cách commit một mức chi tiêu compute tối thiểu mỗi giờ.
# Kiem tra muc chi tieu Lambda hien tai de tinh Savings Plan phu hop
aws ce get-cost-and-usage \
--time-period Start=2026-01-01,End=2026-03-01 \
--granularity MONTHLY \
--metrics "UnblendedCost" \
--filter '{
"Dimensions": {
"Key": "SERVICE",
"Values": ["AWS Lambda"]
}
}' \
--output table
# Xem de xuat Savings Plans tu AWS
aws ce get-savings-plans-purchase-recommendation \
--savings-plans-type "COMPUTE_SP" \
--term-in-years "ONE_YEAR" \
--payment-option "NO_UPFRONT" \
--lookback-period-in-days "THIRTY_DAYS"
Chiến lược mình khuyên dùng: Bắt đầu với Compute Savings Plan No Upfront, 1 năm, covering khoảng 60-70% mức chi tiêu compute tối thiểu. Phần còn lại giữ On-Demand để linh hoạt cho growth. Đừng tham cover 100% — bạn cần room để scale.
8. Giám Sát Và Tự Động Hóa Tối Ưu Chi Phí
8.1 Thiết Lập CloudWatch Alarm Cho Chi Phí Bất Thường
Phòng bệnh hơn chữa bệnh. Đặt alarm sớm để không bị bất ngờ khi cuối tháng nhìn bill:
# Tao CloudWatch Alarm khi chi phi Lambda vuot nguong
aws cloudwatch put-metric-alarm \
--alarm-name "lambda-cost-spike-alarm" \
--alarm-description "Canh bao khi Lambda invocations tang dot bien" \
--metric-name Invocations \
--namespace AWS/Lambda \
--statistic Sum \
--period 3600 \
--threshold 100000 \
--comparison-operator GreaterThanThreshold \
--evaluation-periods 1 \
--alarm-actions "arn:aws:sns:ap-southeast-1:123456789:cost-alerts" \
--treat-missing-data notBreaching
# Tao AWS Budget rieng cho serverless
aws budgets create-budget \
--account-id 123456789012 \
--budget '{
"BudgetName": "Serverless-Monthly-Budget",
"BudgetLimit": {
"Amount": "500",
"Unit": "USD"
},
"BudgetType": "COST",
"TimeUnit": "MONTHLY",
"CostFilters": {
"Service": ["AWS Lambda", "Amazon API Gateway", "AWS Step Functions"]
}
}' \
--notifications-with-subscribers '[{
"Notification": {
"NotificationType": "ACTUAL",
"ComparisonOperator": "GREATER_THAN",
"Threshold": 80,
"ThresholdType": "PERCENTAGE"
},
"Subscribers": [{
"SubscriptionType": "EMAIL",
"Address": "[email protected]"
}]
}]'
8.2 Tối Ưu Logging — Chi Phí Ẩn Lớn Nhất
Nói thật, CloudWatch Logs là một trong những chi phí ẩn mà mình thấy nhiều team "đau" nhất. Mỗi function tự động gửi logs đến CloudWatch, và ở quy mô lớn, chi phí logging có thể vượt cả chi phí compute. Không đùa đâu.
# Dat log retention ngan hon cho functions khong quan trong
aws logs put-retention-policy \
--log-group-name "/aws/lambda/my-api-handler" \
--retention-in-days 14
# Script giam retention cho tat ca Lambda log groups
for LOG_GROUP in $(aws logs describe-log-groups \
--log-group-name-prefix "/aws/lambda/" \
--query "logGroups[?retentionInDays==null || retentionInDays > \`30\`].logGroupName" \
--output text); do
echo "Setting 14-day retention for: $LOG_GROUP"
aws logs put-retention-policy \
--log-group-name "$LOG_GROUP" \
--retention-in-days 14
done
9. So Sánh Chi Phí: Khi Nào Nên Và Không Nên Dùng Serverless
9.1 Serverless Phù Hợp Nhất Với Workload Nào?
Nói thẳng: serverless không phải giải pháp cho mọi thứ. Mình thấy nhiều team cứ "serverless hóa" mọi thứ rồi thắc mắc sao bill cao. Vậy khi nào nên và không nên dùng?
- Nên dùng serverless: API với traffic không đều, xử lý sự kiện (event processing), cron jobs nhẹ, webhook handlers, file processing khi upload.
- Không nên dùng serverless: Workload chạy liên tục 24/7 với traffic ổn định (container trên ECS/EKS rẻ hơn), xử lý batch lớn kéo dài hơn 15 phút, ứng dụng cần kết nối database liên tục.
9.2 Công Thức Tính Break-Even
Muốn biết serverless có rẻ hơn container cho workload cụ thể của bạn không? Dùng công thức này:
# Cong thuc tinh diem hoa von Serverless vs Container
# Chi phi Lambda hang thang
lambda_cost_per_request = (memory_gb * duration_sec * 0.0000166667) + 0.0000002
lambda_monthly = lambda_cost_per_request * monthly_requests
# Chi phi ECS Fargate tuong duong
fargate_vcpu_cost = 0.04048 * 24 * 30 # per vCPU/thang
fargate_memory_cost = 0.004445 * memory_gb * 24 * 30 # per GB/thang
fargate_monthly = fargate_vcpu_cost + fargate_memory_cost # cho 1 task chay 24/7
# Vi du: Function 512MB, chay 200ms
# Lambda: (0.5 * 0.2 * 0.0000166667 + 0.0000002) * requests
# = 0.00000186667 * requests
#
# Fargate (0.25 vCPU, 512MB):
# = 0.04048 * 720 + 0.004445 * 0.5 * 720 = $30.75/thang
#
# Break-even: 30.75 / 0.00000186667 = ~16.5 trieu requests/thang
#
# -> Duoi 16.5 trieu requests/thang: Lambda re hon
# -> Tren 16.5 trieu requests/thang: Fargate re hon
Con số 16.5 triệu requests/tháng là điểm hòa vốn cho ví dụ trên. Workload của bạn sẽ có con số khác tùy thuộc vào memory và duration — nhưng ít nhất bạn đã có framework để tính toán.
Câu Hỏi Thường Gặp (FAQ)
AWS Lambda có thể tiết kiệm được bao nhiêu chi phí so với EC2?
Với workload có traffic không đều, Lambda có thể tiết kiệm 40-70% so với EC2 On-Demand. Tuy nhiên, với workload chạy liên tục 24/7 có traffic ổn định, EC2 với Reserved Instances hoặc Savings Plans thường rẻ hơn. Điểm hòa vốn phụ thuộc vào memory, duration và số lượng requests — hãy dùng công thức break-even ở trên để tính cho trường hợp cụ thể của bạn.
Làm thế nào để giảm chi phí cold start trên serverless?
Ba cách chính: (1) Dùng Provisioned Concurrency trên AWS Lambda hoặc Premium Plan trên Azure Functions cho các function quan trọng nhất, (2) Giữ package size nhỏ nhất có thể để giảm thời gian khởi tạo, (3) Chọn runtime nhẹ như Python hoặc Node.js thay vì Java hay .NET. Trên Google Cloud Functions thế hệ 2, minimum instances là lựa chọn đơn giản và tiết kiệm nhất.
Compute Savings Plans có áp dụng cho Lambda không?
Có, và đây là điều nhiều người bỏ lỡ. AWS Compute Savings Plans áp dụng cho Lambda, EC2 và Fargate. Tiết kiệm thêm 17% chi phí Lambda bằng cách commit mức chi tiêu compute tối thiểu hàng giờ. Khuyến nghị: bắt đầu với No Upfront, 1 năm, covering 60-70% mức chi tiêu tối thiểu.
Chi phí logging CloudWatch có thể giảm bằng cách nào?
Ba cách hiệu quả nhất: (1) Đặt log retention ngắn — 14 ngày cho dev, 30-90 ngày cho production. (2) Giảm log level trong production — chỉ log WARNING trở lên thay vì DEBUG (cái này nghe hiển nhiên nhưng rất nhiều team quên). (3) Chuyển logs cũ sang S3 với Lifecycle Policy để lưu trữ dài hạn với chi phí thấp hơn nhiều.
Nên chọn AWS Lambda, Azure Functions hay Google Cloud Functions?
Thành thật mà nói, cả ba nền tảng có pricing khá tương đồng. Sự khác biệt thực sự nằm ở ecosystem: chọn AWS Lambda nếu bạn đã dùng nhiều dịch vụ AWS, Azure Functions nếu tổ chức dùng Microsoft stack (.NET, Azure AD), và Google Cloud Functions nếu ưu tiên cold start nhanh. Nhưng quan trọng hơn provider là cách bạn tối ưu — đó mới là nơi tiết kiệm thật sự.