Serverless ile Zamanlanmış Görev Otomasyonu
Zamanlanmış görevler, her sistem yöneticisinin hayatının ayrılmaz bir parçası. Yıllarca cron job’lar bizim en sadık dostumuzdu. Gece yarısı çalışan backup scriptleri, sabah 6’da tetiklenen rapor üretimleri, her saat başı kontrol eden monitoring görevleri… Ama bu klasik yaklaşımın ciddi sorunları var: Sunucu ayakta olmalı, kaynaklar boşta bile tüketiliyor, ölçekleme başağrısı yaratıyor ve bir şeyler ters gittiğinde fark etmek zaman alıyor. Serverless mimari bu tabloyu kökten değiştiriyor. AWS Lambda, Google Cloud Functions veya Azure Functions kullanarak zamanlanmış görevlerinizi sunucu yönetimi derdi olmadan, maliyet etkin ve güvenilir şekilde çalıştırabilirsiniz.
Neden Serverless Zamanlanmış Görevler?
Klasik cron yaklaşımının sorunlarına biraz daha bakalım. Bir VM üzerinde çalışan 50 cron job düşünün. Bu VM’in maliyeti sürekli akıyor. Görevler günde toplam 2 saat çalışsa bile, VM 7/24 ayakta duruyor. Serverless’ta ise sadece çalışma süresi için ödeme yapıyorsunuz.
Bunun yanında güvenilirlik meselesi var. Sunucu down olduğunda cron job çalışmıyor ve çoğu zaman kimse fark etmiyor. Serverless platformlar yönetilen altyapı üzerinde çalıştığı için bu riski platform sağlayıcısına devrediyorsunuz.
Ölçekleme de bir başka avantaj. Aylık fatura raporunu işlerken normalde küçük bir script yeterli olurken, ay sonu yüz binlerce kaydı işlemek gerektiğinde serverless otomatik ölçekleniyor. Siz sadece mantığı yazıyorsunuz.
Son olarak gözlemlenebilirlik. CloudWatch, Stackdriver veya Azure Monitor entegrasyonuyla her görev çalışmasının loglarını, sürelerini ve hatalarını merkezi olarak takip edebiliyorsunuz. Eski cron log’larını grep’lemek yerine gerçek bir monitoring deneyimi yaşıyorsunuz.
AWS Lambda ve EventBridge ile Başlangıç
AWS ekosisteminde zamanlanmış görevler için Lambda + EventBridge ikilisi standart çözüm haline geldi. EventBridge, eski CloudWatch Events’in yerini alan daha güçlü bir event bus servisi.
Önce basit bir senaryo ile başlayalım: Her gece saat 02:00’de veritabanı istatistiklerini çeken ve S3’e kaydeden bir görev.
# AWS CLI ile Lambda fonksiyonu oluşturmak için önce IAM rolü gerekiyor
aws iam create-role
--role-name lambda-scheduler-role
--assume-role-policy-document '{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Principal": {"Service": "lambda.amazonaws.com"},
"Action": "sts:AssumeRole"
}]
}'
# Temel Lambda ve S3 izinlerini ekle
aws iam attach-role-policy
--role-name lambda-scheduler-role
--policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
aws iam attach-role-policy
--role-name lambda-scheduler-role
--policy-arn arn:aws:iam::aws:policy/AmazonS3FullAccess
Lambda fonksiyonunuzu Python ile yazalım. Bu script her çalıştığında bir PostgreSQL veritabanından basit istatistikler çekiyor:
# Önce deployment paketi hazırlayalım
mkdir -p /tmp/lambda-package
cat > /tmp/lambda-package/handler.py << 'EOF'
import json
import boto3
import psycopg2
import os
from datetime import datetime
def lambda_handler(event, context):
# Bağlantı bilgilerini Secrets Manager'dan çek
sm_client = boto3.client('secretsmanager')
secret = sm_client.get_secret_value(SecretId='prod/db/credentials')
db_creds = json.loads(secret['SecretString'])
conn = psycopg2.connect(
host=db_creds['host'],
database=db_creds['dbname'],
user=db_creds['username'],
password=db_creds['password']
)
cursor = conn.cursor()
cursor.execute("""
SELECT
schemaname,
tablename,
n_live_tup as row_count,
pg_size_pretty(pg_total_relation_size(schemaname||'.'||tablename)) as total_size
FROM pg_stat_user_tables
ORDER BY n_live_tup DESC
LIMIT 20
""")
results = []
for row in cursor.fetchall():
results.append({
'schema': row[0],
'table': row[1],
'row_count': row[2],
'total_size': row[3]
})
cursor.close()
conn.close()
# S3'e kaydet
s3_client = boto3.client('s3')
timestamp = datetime.now().strftime('%Y/%m/%d/%H%M%S')
s3_key = f"db-stats/{timestamp}/report.json"
s3_client.put_object(
Bucket=os.environ['REPORT_BUCKET'],
Key=s3_key,
Body=json.dumps(results, indent=2),
ContentType='application/json'
)
print(f"Rapor kaydedildi: s3://{os.environ['REPORT_BUCKET']}/{s3_key}")
return {'statusCode': 200, 'body': f'{len(results)} tablo istatistiği kaydedildi'}
EOF
# Gerekli kütüphaneleri yükle
pip install psycopg2-binary -t /tmp/lambda-package/
# Zip paketi oluştur
cd /tmp/lambda-package && zip -r9 /tmp/db-stats-lambda.zip .
Şimdi bu Lambda’yı deploy edelim ve EventBridge kuralı oluşturalım:
# Lambda fonksiyonunu oluştur
ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
aws lambda create-function
--function-name db-stats-collector
--runtime python3.11
--handler handler.lambda_handler
--role arn:aws:iam::${ACCOUNT_ID}:role/lambda-scheduler-role
--zip-file fileb:///tmp/db-stats-lambda.zip
--timeout 300
--memory-size 256
--environment Variables="{REPORT_BUCKET=my-reports-bucket}"
--vpc-config SubnetIds=subnet-abc123,SecurityGroupIds=sg-xyz789
# EventBridge kuralı oluştur - Her gece 02:00 UTC
aws events put-rule
--name "nightly-db-stats"
--schedule-expression "cron(0 2 * * ? *)"
--state ENABLED
--description "Her gece saat 02:00 UTC'de DB istatistiklerini topla"
# Lambda'ya EventBridge'den tetiklenme izni ver
aws lambda add-permission
--function-name db-stats-collector
--statement-id "EventBridgeInvoke"
--action lambda:InvokeFunction
--principal events.amazonaws.com
--source-arn arn:aws:events:eu-west-1:${ACCOUNT_ID}:rule/nightly-db-stats
# EventBridge kuralını Lambda'ya bağla
aws events put-targets
--rule "nightly-db-stats"
--targets Id=1,Arn=arn:aws:lambda:eu-west-1:${ACCOUNT_ID}:function:db-stats-collector
Terraform ile Infrastructure as Code Yaklaşımı
Elle CLI komutları çalıştırmak kabul edilemez. Gerçek dünyada bu yapıyı Terraform ile yönetmeniz gerekiyor. İşte production’a hazır bir Terraform modülü:
# Terraform konfigürasyonu - main.tf
cat > main.tf << 'EOF'
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = "~> 5.0"
}
}
}
# Lambda için IAM rolü
resource "aws_iam_role" "scheduler_lambda" {
name = "scheduler-lambda-${var.environment}"
assume_role_policy = jsonencode({
Version = "2012-10-17"
Statement = [{
Action = "sts:AssumeRole"
Effect = "Allow"
Principal = {
Service = "lambda.amazonaws.com"
}
}]
})
}
resource "aws_iam_role_policy" "scheduler_lambda" {
name = "scheduler-lambda-policy"
role = aws_iam_role.scheduler_lambda.id
policy = jsonencode({
Version = "2012-10-17"
Statement = [
{
Effect = "Allow"
Action = [
"logs:CreateLogGroup",
"logs:CreateLogStream",
"logs:PutLogEvents"
]
Resource = "arn:aws:logs:*:*:*"
},
{
Effect = "Allow"
Action = [
"s3:PutObject",
"s3:GetObject"
]
Resource = "${aws_s3_bucket.reports.arn}/*"
},
{
Effect = "Allow"
Action = ["secretsmanager:GetSecretValue"]
Resource = var.db_secret_arn
},
{
Effect = "Allow"
Action = [
"ec2:CreateNetworkInterface",
"ec2:DescribeNetworkInterfaces",
"ec2:DeleteNetworkInterface"
]
Resource = "*"
}
]
})
}
# CloudWatch Log Group - explicit tanımla ki destroy'da silinsin
resource "aws_cloudwatch_log_group" "db_stats" {
name = "/aws/lambda/db-stats-collector-${var.environment}"
retention_in_days = 30
}
# Lambda fonksiyonu
resource "aws_lambda_function" "db_stats" {
filename = data.archive_file.lambda_zip.output_path
function_name = "db-stats-collector-${var.environment}"
role = aws_iam_role.scheduler_lambda.arn
handler = "handler.lambda_handler"
runtime = "python3.11"
timeout = 300
memory_size = 256
source_code_hash = data.archive_file.lambda_zip.output_base64sha256
environment {
variables = {
REPORT_BUCKET = aws_s3_bucket.reports.bucket
DB_SECRET_ARN = var.db_secret_arn
ENVIRONMENT = var.environment
}
}
vpc_config {
subnet_ids = var.private_subnet_ids
security_group_ids = [aws_security_group.lambda.id]
}
depends_on = [aws_cloudwatch_log_group.db_stats]
}
# EventBridge zamanlaması
resource "aws_cloudwatch_event_rule" "nightly_db_stats" {
name = "nightly-db-stats-${var.environment}"
description = "Her gece saat 02:00 UTC'de DB istatistiklerini topla"
schedule_expression = "cron(0 2 * * ? *)"
}
resource "aws_cloudwatch_event_target" "db_stats_lambda" {
rule = aws_cloudwatch_event_rule.nightly_db_stats.name
target_id = "DbStatsLambda"
arn = aws_lambda_function.db_stats.arn
}
resource "aws_lambda_permission" "eventbridge" {
statement_id = "AllowEventBridgeInvoke"
action = "lambda:InvokeFunction"
function_name = aws_lambda_function.db_stats.function_name
principal = "events.amazonaws.com"
source_arn = aws_cloudwatch_event_rule.nightly_db_stats.arn
}
# CloudWatch Alarm - Lambda hata durumunda bildirim
resource "aws_cloudwatch_metric_alarm" "lambda_errors" {
alarm_name = "db-stats-lambda-errors-${var.environment}"
comparison_operator = "GreaterThanThreshold"
evaluation_periods = "1"
metric_name = "Errors"
namespace = "AWS/Lambda"
period = "300"
statistic = "Sum"
threshold = "0"
alarm_description = "Lambda fonksiyonu hata verdi"
alarm_actions = [var.sns_topic_arn]
dimensions = {
FunctionName = aws_lambda_function.db_stats.function_name
}
}
EOF
echo "Terraform konfigürasyonu oluşturuldu"
Google Cloud Functions ile Alternatif Yaklaşım
AWS dışında çalışıyorsanız Google Cloud Functions + Cloud Scheduler kombinasyonu aynı işlevi görüyor. GCP’nin avantajı Python, Node.js, Go gibi dillerde daha düzgün yerel runtime desteği sunması.
Şu senaryoyu düşünelim: Her 6 saatte bir Kubernetes cluster’ınızdaki pod kaynaklarını kontrol eden ve anomali tespit eden bir görev.
# gcloud CLI ile Cloud Scheduler ve Function kurulumu
# Önce gerekli API'leri aktifleştir
gcloud services enable cloudfunctions.googleapis.com
gcloud services enable cloudscheduler.googleapis.com
gcloud services enable pubsub.googleapis.com
# Pub/Sub topic oluştur - Scheduler bu topic'e mesaj atacak
gcloud pubsub topics create k8s-health-check-trigger
# Cloud Function için servis hesabı oluştur
gcloud iam service-accounts create k8s-health-checker
--display-name="K8s Health Checker Function"
SA_EMAIL="k8s-health-checker@$(gcloud config get-value project).iam.gserviceaccount.com"
# GKE'ye okuma yetkisi ver
gcloud projects add-iam-policy-binding $(gcloud config get-value project)
--member="serviceAccount:${SA_EMAIL}"
--role="roles/container.viewer"
# Cloud Logging yazma yetkisi
gcloud projects add-iam-policy-binding $(gcloud config get-value project)
--member="serviceAccount:${SA_EMAIL}"
--role="roles/logging.logWriter"
# Cloud Function'ı deploy et
mkdir -p /tmp/k8s-checker
cat > /tmp/k8s-checker/main.py << 'PYEOF'
import json
import base64
from kubernetes import client, config
from google.cloud import logging as gcloud_logging
import functions_framework
@functions_framework.cloud_event
def check_k8s_health(cloud_event):
log_client = gcloud_logging.Client()
logger = log_client.logger('k8s-health-check')
config.load_incluster_config()
v1 = client.CoreV1Api()
# Tüm pod'ları kontrol et
pods = v1.list_pod_for_all_namespaces(watch=False)
problematic_pods = []
for pod in pods.items:
if pod.status.phase in ['Failed', 'Unknown', 'Pending']:
# Pending pod'ları 5 dakikadan uzunsa sorunlu say
problematic_pods.append({
'name': pod.metadata.name,
'namespace': pod.metadata.namespace,
'phase': pod.status.phase,
'reason': pod.status.reason or 'Bilinmiyor'
})
if problematic_pods:
logger.log_struct({
'severity': 'WARNING',
'message': f'{len(problematic_pods)} sorunlu pod tespit edildi',
'pods': problematic_pods
})
else:
logger.log_struct({
'severity': 'INFO',
'message': 'Tüm pod'lar sağlıklı',
'total_pods': len(pods.items)
})
PYEOF
cat > /tmp/k8s-checker/requirements.txt << 'EOF'
kubernetes==28.1.0
google-cloud-logging==3.8.0
functions-framework==3.5.0
EOF
gcloud functions deploy k8s-health-checker
--gen2
--runtime=python311
--region=europe-west1
--source=/tmp/k8s-checker
--entry-point=check_k8s_health
--trigger-topic=k8s-health-check-trigger
--service-account="${SA_EMAIL}"
--memory=256MB
--timeout=120s
# Cloud Scheduler job oluştur - Her 6 saatte bir
gcloud scheduler jobs create pubsub k8s-health-check
--location=europe-west1
--schedule="0 */6 * * *"
--topic=k8s-health-check-trigger
--message-body='{"trigger": "scheduled"}'
--time-zone="Europe/Istanbul"
--description="Her 6 saatte bir K8s pod sağlık kontrolü"
Hata Yönetimi ve Retry Mekanizmaları
Serverless zamanlanmış görevlerde en çok göz ardı edilen konu hata yönetimi. Bir Lambda başarısız olduğunda ne oluyor? Varsayılan davranış yetersiz çoğu senaryoda.
# Dead Letter Queue (DLQ) kurulumu - başarısız invocation'ları yakala
aws sqs create-queue
--queue-name scheduler-dlq
--attributes '{
"MessageRetentionPeriod": "1209600",
"VisibilityTimeout": "300"
}'
DLQ_ARN=$(aws sqs get-queue-attributes
--queue-url $(aws sqs get-queue-url --queue-name scheduler-dlq --query QueueUrl --output text)
--attribute-names QueueArn
--query Attributes.QueueArn
--output text)
# Lambda'yı DLQ ile güncelle
aws lambda update-function-configuration
--function-name db-stats-collector
--dead-letter-config TargetArn=${DLQ_ARN}
# EventBridge retry politikası - varsayılan olarak 185 saat deniyor
# Bunu daha makul bir değere çekelim
aws events put-targets
--rule "nightly-db-stats"
--targets '[{
"Id": "1",
"Arn": "arn:aws:lambda:eu-west-1:ACCOUNT_ID:function:db-stats-collector",
"RetryPolicy": {
"MaximumRetryAttempts": 3,
"MaximumEventAgeInSeconds": 3600
}
}]'
# DLQ'daki mesajları işleyen alarm - hata durumunda SNS bildirimi
aws cloudwatch put-metric-alarm
--alarm-name "scheduler-dlq-messages"
--metric-name "ApproximateNumberOfMessagesVisible"
--namespace "AWS/SQS"
--statistic Sum
--period 300
--threshold 1
--comparison-operator GreaterThanOrEqualToThreshold
--dimensions Name=QueueName,Value=scheduler-dlq
--evaluation-periods 1
--alarm-actions arn:aws:sns:eu-west-1:ACCOUNT_ID:ops-alerts
--alarm-description "Zamanlanmis gorev basarisiz oldu - DLQ'da mesaj var"
Karmaşık Senaryolar: Step Functions ile Orchestration
Basit tek adımlı görevler Lambda ile çözülüyor. Ama ya birden fazla adım içeren, bazı adımların paralel çalışması gereken iş akışları? AWS Step Functions burada devreye giriyor.
Örnek senaryo: Her sabah 07:00’de çalışan aylık fatura hazırlama süreci.
# Step Functions state machine tanımı
cat > /tmp/billing-workflow.json << 'EOF'
{
"Comment": "Aylık fatura hazırlama iş akışı",
"StartAt": "CollectUsageData",
"States": {
"CollectUsageData": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-west-1:ACCOUNT_ID:function:collect-usage-data",
"Retry": [{
"ErrorEquals": ["Lambda.ServiceException", "Lambda.TooManyRequestsException"],
"IntervalSeconds": 30,
"MaxAttempts": 3,
"BackoffRate": 2
}],
"Catch": [{
"ErrorEquals": ["States.ALL"],
"Next": "NotifyFailure"
}],
"Next": "ProcessInParallel"
},
"ProcessInParallel": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "GenerateInvoices",
"States": {
"GenerateInvoices": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-west-1:ACCOUNT_ID:function:generate-invoices",
"End": true
}
}
},
{
"StartAt": "UpdateMetrics",
"States": {
"UpdateMetrics": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-west-1:ACCOUNT_ID:function:update-billing-metrics",
"End": true
}
}
}
],
"Next": "SendNotifications",
"Catch": [{
"ErrorEquals": ["States.ALL"],
"Next": "NotifyFailure"
}]
},
"SendNotifications": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-west-1:ACCOUNT_ID:function:send-billing-notifications",
"End": true
},
"NotifyFailure": {
"Type": "Task",
"Resource": "arn:aws:lambda:eu-west-1:ACCOUNT_ID:function:notify-failure",
"End": true
}
}
}
EOF
# State machine oluştur
aws stepfunctions create-state-machine
--name billing-workflow
--definition file:///tmp/billing-workflow.json
--role-arn arn:aws:iam::ACCOUNT_ID:role/stepfunctions-role
--type STANDARD
# EventBridge ile Step Functions'ı tetikle - her sabah 07:00 İstanbul saati (04:00 UTC)
aws events put-rule
--name "monthly-billing-trigger"
--schedule-expression "cron(0 4 1 * ? *)"
--state ENABLED
aws events put-targets
--rule "monthly-billing-trigger"
--targets '[{
"Id": "1",
"Arn": "arn:aws:states:eu-west-1:ACCOUNT_ID:stateMachine:billing-workflow",
"RoleArn": "arn:aws:iam::ACCOUNT_ID:role/eventbridge-stepfunctions-role"
}]'
Gözlemlenebilirlik ve Monitoring
Serverless görevleri kör uçmak istemiyorsanız, monitoring’e yatırım yapmalısınız. CloudWatch Logs Insights ile log analizi için güçlü sorgular yazabilirsiniz:
# Son 24 saatteki tüm Lambda çalışmalarını analiz et
aws logs start-query
--log-group-name "/aws/lambda/db-stats-collector-production"
--start-time $(date -d '24 hours ago' +%s)
--end-time $(date +%s)
--query-string '
fields @timestamp, @duration, @billedDuration, @memorySize, @maxMemoryUsed
| filter @type = "REPORT"
| stats
count() as invocations,
avg(@duration) as avg_duration_ms,
max(@duration) as max_duration_ms,
avg(@maxMemoryUsed) as avg_memory_mb,
sum(filter(@duration, @initDuration > 0)) as cold_starts
by bin(1h)
| sort @timestamp desc
'
# Sorgu sonuçlarını getir
QUERY_ID=$(aws logs start-query
--log-group-name "/aws/lambda/db-stats-collector-production"
--start-time $(date -d '24 hours ago' +%s)
--end-time $(date +%s)
--query-string 'fields @timestamp, @message | filter @message like /ERROR/ | limit 50'
--query queryId
--output text)
sleep 5
aws logs get-query-results --query-id ${QUERY_ID}
# Lambda metriklerini dashboard'a ekle - custom metric
aws cloudwatch put-metric-data
--namespace "CustomScheduler"
--metric-name "TaskDuration"
--value 45.2
--unit Seconds
--dimensions FunctionName=db-stats-collector,Environment=production
Maliyet Optimizasyonu Taktikleri
Serverless ucuz ama dikkatsiz kullanım maliyetleri artırabilir. Birkaç somut öneri:
- Memory ayarı kritik: Lambda’da CPU, memory ile orantılı. 512MB yerine 1024MB verirseniz hem maliyet artıyor hem de bazı durumlarda daha hızlı bittiği için net maliyet aynı kalıyor. AWS Lambda Power Tuning aracı ile optimal bellek değerini test edin.
- Timeout değerlerine dikkat: Göreviniz normalde 30 saniyede bitiyor ama timeout 900 saniye ayarlıysanız, bir şeyler ters gittiğinde tam 15 dakika boyunca para yanıyor. Gerçekçi timeout değerleri kullanın.
- Provisioned Concurrency’den kaçının: Zamanlanmış görevler için cold start genellikle sorun değil. Provisioned concurrency sürekli para harcar, sadece latency kritik API endpoint’leri için kullanın.
- Arm64 mimarisine geçin: AWS Graviton2 işlemcilerle Lambda çalıştırmak x86’ya göre yaklaşık %20 daha ucuz ve genellikle daha hızlı.
- Boş çalışmaları izleyin: Bir görev “veri yok, çıkıyorum” diyerek 2 saniyede bitiyorsa, bu invocation maliyeti minimal. Ama loglayın ki gerçekten çalıştığını doğrulayabilesiniz.
- Reserved concurrency ile koruma: Bir Lambda’nın diğer kritik fonksiyonlardan kaynak çalmasını önlemek için reserved concurrency sınırı koyun.
Gerçek Dünya Sorunları ve Çözümleri
Çift çalışma problemi: EventBridge nadiren de olsa aynı eventi iki kez gönderebilir. Kritik görevleriniz idempotent olmalı. S3’e yazarken aynı key’i kullanın, veritabanına yazarken UPSERT kullanın.
Timezone karmaşası: EventBridge cron ifadeleri UTC kullanır. İstanbul için UTC+3 farkını aklınızda tutun. Yaz saati uygulamasında bu +3 olurken kış saatinde aynı kalıyor. Kod içinde timezone dönüşümü yaparken pytz veya zoneinfo kütüphanelerini kullanın, elle saat eklemeye kalkmayın.
VPC soğuk başlatma gecikmesi: Lambda’nızı VPC içinde çalıştırıyorsanız (ki veritabanına erişmek için genellikle gerekiyor), ilk başlatma birkaç saniye daha uzun sürebilir. Bu zamanlanmış görevler için kritik değil ama bilinmesinde fayda var.
Concurrency limitleri: Aynı anda çok sayıda zamanlanmış göreve sahipseniz ve hepsi aynı anda tetikleniyorsa, hesap bazlı concurrency limitine takılabilirsiniz. Görevleri farklı dakikalara yayın.
Sonuç
Serverless zamanlanmış görev otomasyonu, doğru kurulduğunda klasik cron yaklaşımına göre ciddi avantajlar sunuyor. Sunucu yönetimi derdi yok, maliyet çalışma süresiyle orantılı, ölçekleme otomatik ve monitoring çok daha güçlü.
Başlangıç için şu adım sırasını öneririm: Önce en az kritik, en basit görevinizi serverless’a taşıyın. Lambda + EventBridge kurulumunu öğrenin, monitoring’i doğru yapılandırın, hata bildirimlerini aktif edin. Bir ay boyunca gözlemleyin. Sonra diğer görevleri de migrate edin. Karmaşık iş akışları için Step Functions’a geçişi ertelemeyın, uzun vadede çok daha sürdürülebilir.
Infrastructure as Code olmadan production’a çıkmayın. Terraform veya Pulumi ile tüm kaynakları kod olarak yönetin. Altı ay sonra “bu Lambda’yı kim ne zaman neden oluşturdu” sorusuna cevap bulmaya çalışmak istemezsiniz.
Son olarak, serverless her şeyin çözümü değil. Çok uzun süren görevler (15 dakikadan fazla), stateful işlemler veya çok sık tetiklenen görevler (dakikada birden fazla) için farklı yaklaşımlar daha uygun olabilir. Ama büyük çoğunluğu oluşturan “arada bir çalışan, belirli işi yapan” görevler için serverless gerçekten doğru seçim.
