Serverless ile Mikroservis Mimarisi Tasarımı

Mikroservis mimarisini serverless ile birleştirmek, ilk bakışta biraz kafa karıştırıcı gelebilir. “Zaten mikroservislerim var, neden serverless?” sorusu aklına gelebilir. Ama bu iki yaklaşımı doğru şekilde harmanlayınca ortaya çıkan mimari, hem ölçeklenebilirlik hem de maliyet açısından ciddi avantajlar sunuyor. Bu yazıda gerçek dünya senaryoları üzerinden serverless ve mikroservis mimarisini nasıl tasarlayacağını, hangi tuzaklardan kaçınacağını ve production’da ne işe yaradığını anlatacağım.

Serverless Nedir, Mikroservis ile Farkı Ne?

Klasik mikroservis mimarisinde her servisin kendi container’ı, kendi process’i ve kendi yaşam döngüsü vardır. Kubernetes üzerinde çalışıyorsan deployment, service, ingress tanımları yapıyorsun, health check’lerle uğraşıyorsun, pod’ların scale olmasını yönetiyorsun.

Serverless’ta ise sen sadece kodu yazıyorsun. Altyapı tamamen cloud provider’ın elinde. AWS Lambda, Google Cloud Functions veya Azure Functions gibi servisler fonksiyonunu çalıştırıyor, işi bitince kaynakları serbest bırakıyor. Sen sadece kullandığın süre için ödüyorsun.

Temel fark şu: Mikroservis bir mimari yaklaşım, serverless ise bir deployment ve çalıştırma modelidir. Bu yüzden birbirinin alternatifi değil, tamamlayıcısıdır.

Gerçek dünya örneği verecek olursam: Bir e-ticaret platformu düşün. Sipariş yönetimi, kullanıcı yönetimi, envanter servisi gibi core business logic’ler için container tabanlı mikroservisler kullanırsın çünkü bu servisler sürekli ayakta olmalı ve düşük latency gerektirir. Ama email bildirimi gönderme, PDF fatura oluşturma, stok raporu hazırlama gibi event-driven ve aralıklı çalışan işler için serverless fonksiyonlar çok daha mantıklıdır.

Mimari Tasarım Prensipleri

Serverless-mikroservis hibrit mimarisi tasarlarken birkaç temel prensibi aklında tutman gerekiyor.

Single Responsibility: Her Lambda fonksiyonu tek bir iş yapmalı. “Sipariş oluştur ve email gönder ve envanteri güncelle” yapan bir fonksiyon değil, bunların her biri ayrı fonksiyon olmalı.

Event-Driven Communication: Servisler arasındaki iletişim mümkün olduğunca event’ler üzerinden kurulmalı. AWS SQS, SNS veya EventBridge bu noktada devreye giriyor.

Stateless Functions: Lambda fonksiyonların herhangi bir local state tutmaması gerekiyor. State her zaman dış sistemlerde (DynamoDB, Redis, S3) yaşamalı.

Fail Fast: Fonksiyonların hızlı başarısız olması ve retry mekanizmalarının doğru kurulması kritik.

Proje Yapısını Kurmak

Önce serverless framework kurulumunu yapalım. AWS Lambda için Serverless Framework veya AWS SAM kullanabilirsin. Ben Serverless Framework’ü tercih ediyorum çünkü çok provider desteği var ve konfigürasyon daha okunaklı.

# Node.js kurulu olduğunu varsayarak
npm install -g serverless

# AWS credentials ayarla
aws configure
# Access Key ID, Secret Access Key, Region gir

# Yeni proje oluştur
serverless create --template aws-nodejs-typescript --path ecommerce-serverless
cd ecommerce-serverless

# Gerekli plugin'leri kur
npm install --save-dev serverless-offline serverless-plugin-typescript
npm install aws-sdk @aws-sdk/client-dynamodb @aws-sdk/client-sqs

Proje dizin yapısı şu şekilde olmalı:

mkdir -p src/{orders,inventory,notifications,shared}
mkdir -p src/shared/{models,utils,middleware}

# Dosya yapısı
tree src/
# src/
# ├── orders/
# │   ├── createOrder.ts
# │   ├── getOrder.ts
# │   └── updateOrderStatus.ts
# ├── inventory/
# │   ├── updateStock.ts
# │   └── checkAvailability.ts
# ├── notifications/
# │   ├── sendEmail.ts
# │   └── sendSMS.ts
# └── shared/
#     ├── models/
#     ├── utils/
#     └── middleware/

Sipariş Servisi Lambda Fonksiyonu

Gerçek bir örnek üzerinden gidelim. Sipariş oluşturma fonksiyonu şu şekilde yazılabilir:

# serverless.yml - Ana konfigürasyon dosyası
cat > serverless.yml << 'EOF'
service: ecommerce-platform

frameworkVersion: '3'

provider:
  name: aws
  runtime: nodejs18.x
  region: eu-west-1
  environment:
    ORDERS_TABLE: ${self:service}-orders-${sls:stage}
    INVENTORY_TABLE: ${self:service}-inventory-${sls:stage}
    ORDER_EVENTS_QUEUE: !Ref OrderEventsQueue
    NOTIFICATION_TOPIC: !Ref NotificationTopic
  iam:
    role:
      statements:
        - Effect: Allow
          Action:
            - dynamodb:PutItem
            - dynamodb:GetItem
            - dynamodb:UpdateItem
            - dynamodb:Query
          Resource:
            - !GetAtt OrdersTable.Arn
        - Effect: Allow
          Action:
            - sqs:SendMessage
            - sqs:ReceiveMessage
            - sqs:DeleteMessage
          Resource:
            - !GetAtt OrderEventsQueue.Arn
        - Effect: Allow
          Action:
            - sns:Publish
          Resource:
            - !Ref NotificationTopic

functions:
  createOrder:
    handler: src/orders/createOrder.handler
    timeout: 30
    memorySize: 256
    events:
      - http:
          path: /orders
          method: post
          cors: true
    environment:
      FUNCTION_NAME: createOrder

  processOrderEvent:
    handler: src/orders/processOrderEvent.handler
    timeout: 60
    memorySize: 512
    events:
      - sqs:
          arn: !GetAtt OrderEventsQueue.Arn
          batchSize: 10
          functionResponseType: ReportBatchItemFailures

  updateInventory:
    handler: src/inventory/updateStock.handler
    timeout: 30
    memorySize: 256
    events:
      - sqs:
          arn: !GetAtt InventoryUpdateQueue.Arn
          batchSize: 5

resources:
  Resources:
    OrdersTable:
      Type: AWS::DynamoDB::Table
      Properties:
        TableName: ${self:provider.environment.ORDERS_TABLE}
        BillingMode: PAY_PER_REQUEST
        AttributeDefinitions:
          - AttributeName: orderId
            AttributeType: S
          - AttributeName: userId
            AttributeType: S
        KeySchema:
          - AttributeName: orderId
            KeyType: HASH
        GlobalSecondaryIndexes:
          - IndexName: UserOrdersIndex
            KeySchema:
              - AttributeName: userId
                KeyType: HASH
            Projection:
              ProjectionType: ALL

    OrderEventsQueue:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: ${self:service}-order-events-${sls:stage}
        VisibilityTimeout: 300
        RedrivePolicy:
          deadLetterTargetArn: !GetAtt OrdersDLQ.Arn
          maxReceiveCount: 3

    OrdersDLQ:
      Type: AWS::SQS::Queue
      Properties:
        QueueName: ${self:service}-orders-dlq-${sls:stage}
        MessageRetentionPeriod: 1209600

    NotificationTopic:
      Type: AWS::SNS::Topic
      Properties:
        TopicName: ${self:service}-notifications-${sls:stage}
EOF

Order Servisinin İş Mantığı

Şimdi asıl fonksiyon kodunu yazalım. Bu kısım TypeScript ama bash ile test edebileceğin şekilde göstereceğim:

# createOrder.ts içeriğini oluştur
cat > src/orders/createOrder.ts << 'EOF'
import { APIGatewayProxyHandler } from 'aws-lambda';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
import { DynamoDBDocumentClient, PutCommand } from '@aws-sdk/lib-dynamodb';
import { SQSClient, SendMessageCommand } from '@aws-sdk/client-sqs';
import { v4 as uuidv4 } from 'uuid';

const dynamoClient = new DynamoDBClient({ region: process.env.AWS_REGION });
const docClient = DynamoDBDocumentClient.from(dynamoClient);
const sqsClient = new SQSClient({ region: process.env.AWS_REGION });

export const handler: APIGatewayProxyHandler = async (event) => {
  try {
    const body = JSON.parse(event.body || '{}');
    const { userId, items, shippingAddress } = body;

    // Input validation
    if (!userId || !items || items.length === 0) {
      return {
        statusCode: 400,
        body: JSON.stringify({ error: 'userId ve items zorunludur' })
      };
    }

    const orderId = uuidv4();
    const totalAmount = items.reduce((sum: number, item: any) => 
      sum + (item.price * item.quantity), 0);

    const order = {
      orderId,
      userId,
      items,
      shippingAddress,
      totalAmount,
      status: 'PENDING',
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString()
    };

    // DynamoDB'ye kaydet
    await docClient.send(new PutCommand({
      TableName: process.env.ORDERS_TABLE!,
      Item: order,
      ConditionExpression: 'attribute_not_exists(orderId)'
    }));

    // SQS'e event gönder - diğer servisler bu event'i dinliyor
    await sqsClient.send(new SendMessageCommand({
      QueueUrl: process.env.ORDER_EVENTS_QUEUE!,
      MessageBody: JSON.stringify({
        eventType: 'ORDER_CREATED',
        orderId,
        userId,
        items,
        totalAmount,
        timestamp: new Date().toISOString()
      }),
      MessageAttributes: {
        eventType: {
          DataType: 'String',
          StringValue: 'ORDER_CREATED'
        }
      }
    }));

    return {
      statusCode: 201,
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ orderId, status: 'PENDING', totalAmount })
    };

  } catch (error) {
    console.error('Order creation failed:', error);
    return {
      statusCode: 500,
      body: JSON.stringify({ error: 'Internal server error' })
    };
  }
};
EOF

Dead Letter Queue ve Hata Yönetimi

Production’da en önemli konulardan biri hata yönetimi. Lambda fonksiyonları başarısız olduğunda ne olacak? DLQ burada kritik rol oynuyor:

# DLQ mesajlarını izlemek ve yeniden işlemek için script
cat > scripts/process-dlq.sh << 'EOF'
#!/bin/bash

DLQ_URL="https://sqs.eu-west-1.amazonaws.com/ACCOUNT_ID/ecommerce-platform-orders-dlq-prod"
MAIN_QUEUE_URL="https://sqs.eu-west-1.amazonaws.com/ACCOUNT_ID/ecommerce-platform-order-events-prod"

echo "DLQ mesaj sayısı kontrol ediliyor..."
MESSAGE_COUNT=$(aws sqs get-queue-attributes 
  --queue-url $DLQ_URL 
  --attribute-names ApproximateNumberOfMessages 
  --query 'Attributes.ApproximateNumberOfMessages' 
  --output text)

echo "DLQ'da $MESSAGE_COUNT mesaj var"

if [ "$MESSAGE_COUNT" -gt "0" ]; then
  echo "Mesajlar ana kuyruğa geri gönderiliyor..."
  
  # DLQ'dan mesajları al
  MESSAGES=$(aws sqs receive-message 
    --queue-url $DLQ_URL 
    --max-number-of-messages 10 
    --attribute-names All)
  
  # Her mesajı ana kuyruğa gönder
  echo $MESSAGES | jq -r '.Messages[] | @base64' | while read msg; do
    DECODED=$(echo $msg | base64 -d)
    BODY=$(echo $DECODED | jq -r '.Body')
    RECEIPT=$(echo $DECODED | jq -r '.ReceiptHandle')
    
    # Ana kuyruğa gönder
    aws sqs send-message 
      --queue-url $MAIN_QUEUE_URL 
      --message-body "$BODY"
    
    # DLQ'dan sil
    aws sqs delete-message 
      --queue-url $DLQ_URL 
      --receipt-handle "$RECEIPT"
    
    echo "Mesaj yeniden kuyruğa alındı: $(echo $BODY | jq -r '.orderId')"
  done
fi
EOF

chmod +x scripts/process-dlq.sh

CloudWatch ile Monitoring Kurulumu

Serverless mimaride monitoring, container tabanlı yaklaşımdan farklı. Her fonksiyon için ayrı metrikler takip etmen gerekiyor:

# CloudWatch alarm ve dashboard oluşturma
cat > scripts/setup-monitoring.sh << 'EOF'
#!/bin/bash

FUNCTION_PREFIX="ecommerce-platform"
STAGE="prod"
SNS_ALARM_TOPIC="arn:aws:sns:eu-west-1:ACCOUNT_ID:alerts"

# Her Lambda fonksiyonu için error alarm kur
FUNCTIONS=("createOrder" "processOrderEvent" "updateInventory" "sendEmail")

for FUNC in "${FUNCTIONS[@]}"; do
  FUNCTION_NAME="${FUNCTION_PREFIX}-${STAGE}-${FUNC}"
  
  # Error rate alarm
  aws cloudwatch put-metric-alarm 
    --alarm-name "${FUNCTION_NAME}-errors" 
    --alarm-description "${FUNC} fonksiyonu hata alıyor" 
    --metric-name Errors 
    --namespace AWS/Lambda 
    --statistic Sum 
    --period 300 
    --threshold 5 
    --comparison-operator GreaterThanThreshold 
    --dimensions Name=FunctionName,Value=$FUNCTION_NAME 
    --evaluation-periods 1 
    --alarm-actions $SNS_ALARM_TOPIC 
    --treat-missing-data notBreaching
  
  # Duration alarm - timeout yaklaşıyorsa uyar
  aws cloudwatch put-metric-alarm 
    --alarm-name "${FUNCTION_NAME}-duration" 
    --alarm-description "${FUNC} fonksiyonu yavaş çalışıyor" 
    --metric-name Duration 
    --namespace AWS/Lambda 
    --statistic p95 
    --period 300 
    --threshold 25000 
    --comparison-operator GreaterThanThreshold 
    --dimensions Name=FunctionName,Value=$FUNCTION_NAME 
    --evaluation-periods 2 
    --alarm-actions $SNS_ALARM_TOPIC
  
  echo "Alarm kuruldu: $FUNCTION_NAME"
done

# Cold start metriği için custom metric gönderme
echo "Custom dashboard oluşturuluyor..."

aws cloudwatch put-dashboard 
  --dashboard-name "EcommerceServerless" 
  --dashboard-body '{
    "widgets": [
      {
        "type": "metric",
        "properties": {
          "title": "Lambda Invocations",
          "metrics": [
            ["AWS/Lambda", "Invocations", "FunctionName", "ecommerce-platform-prod-createOrder"],
            ["AWS/Lambda", "Invocations", "FunctionName", "ecommerce-platform-prod-processOrderEvent"]
          ],
          "period": 300,
          "stat": "Sum",
          "view": "timeSeries"
        }
      }
    ]
  }'

echo "Monitoring kurulumu tamamlandı"
EOF

chmod +x scripts/setup-monitoring.sh

Cold Start Sorununu Çözmek

Serverless mimarisinin en bilinen problemi cold start. Uzun süre istek almayan bir fonksiyon çağrıldığında Lambda container’ı başlatmak zorunda kalıyor ve bu 200ms-2 saniye arasında ekstra gecikme yaratıyor. Bunu birkaç yöntemle azaltabilirsin:

# Provisioned Concurrency ayarla - kritik fonksiyonlar için
aws lambda put-provisioned-concurrency-config 
  --function-name ecommerce-platform-prod-createOrder 
  --qualifier prod 
  --provisioned-concurrent-executions 5

# Warm-up için EventBridge scheduled rule
cat > warmup-rule.sh << 'EOF'
#!/bin/bash

# Her 5 dakikada bir fonksiyonları uyandır
aws events put-rule 
  --name "lambda-warmup-rule" 
  --schedule-expression "rate(5 minutes)" 
  --state ENABLED

# Lambda'yı hedef olarak ekle
aws events put-targets 
  --rule "lambda-warmup-rule" 
  --targets '[
    {
      "Id": "warmup-createOrder",
      "Arn": "arn:aws:lambda:eu-west-1:ACCOUNT_ID:function:ecommerce-platform-prod-createOrder",
      "Input": "{"source": "warmup", "detail-type": "Warmup", "detail": {}}"
    }
  ]'

echo "Warmup kuralı oluşturuldu"
EOF

chmod +x warmup-rule.sh

# Fonksiyon içinde warmup event'ini handle et
cat > src/shared/middleware/warmup.ts << 'EOF'
export const warmupMiddleware = (handler: Function) => {
  return async (event: any, context: any) => {
    // Warmup isteği ise hızlıca dön
    if (event.source === 'warmup') {
      console.log('Warmup isteği - fonksiyon sıcak tutuldu');
      return { statusCode: 200, body: 'Warm!' };
    }
    return handler(event, context);
  };
};
EOF

Servisler Arası İletişim Patternleri

Hibrit mimaride en kritik konu servisler arası iletişim. Senkron HTTP çağrıları yerine asenkron event-driven yaklaşımı tercih etmelisin:

# EventBridge ile servisler arası event routing
cat > src/shared/utils/eventBus.ts << 'EOF'
import { EventBridgeClient, PutEventsCommand } from '@aws-sdk/client-eventbridge';

const eventBridgeClient = new EventBridgeClient({ region: process.env.AWS_REGION });

interface DomainEvent {
  source: string;
  detailType: string;
  detail: Record<string, any>;
}

export async function publishEvent(event: DomainEvent): Promise<void> {
  const command = new PutEventsCommand({
    Entries: [{
      Source: `ecommerce.${event.source}`,
      DetailType: event.detailType,
      Detail: JSON.stringify({
        ...event.detail,
        timestamp: new Date().toISOString(),
        eventId: crypto.randomUUID()
      }),
      EventBusName: process.env.EVENT_BUS_NAME || 'default'
    }]
  });

  const result = await eventBridgeClient.send(command);
  
  if (result.FailedEntryCount && result.FailedEntryCount > 0) {
    throw new Error(`Event publish başarısız: ${JSON.stringify(result.Entries)}`);
  }
}

// Kullanım örneği
// await publishEvent({
//   source: 'orders',
//   detailType: 'OrderStatusChanged',
//   detail: { orderId: '123', newStatus: 'SHIPPED', userId: 'user456' }
// });
EOF

# EventBridge rule - inventory servisini tetikle
aws events put-rule 
  --name "order-created-to-inventory" 
  --event-pattern '{
    "source": ["ecommerce.orders"],
    "detail-type": ["OrderCreated"]
  }' 
  --state ENABLED 
  --event-bus-name ecommerce-events

aws events put-targets 
  --rule "order-created-to-inventory" 
  --event-bus-name ecommerce-events 
  --targets '[
    {
      "Id": "inventory-update-target",
      "Arn": "arn:aws:lambda:eu-west-1:ACCOUNT_ID:function:ecommerce-platform-prod-updateInventory"
    }
  ]'

echo "EventBridge routing kuruldu"

Deployment Pipeline

CI/CD pipeline olmadan serverless mimarisi eksik kalır. GitHub Actions ile otomatik deployment:

# .github/workflows/deploy.yml
cat > .github/workflows/deploy.yml << 'EOF'
name: Deploy Serverless

on:
  push:
    branches:
      - main
      - staging

jobs:
  test-and-deploy:
    runs-on: ubuntu-latest
    
    steps:
      - name: Checkout
        uses: actions/checkout@v3

      - name: Node.js Kur
        uses: actions/setup-node@v3
        with:
          node-version: '18'
          cache: 'npm'

      - name: Bağımlılıkları Yükle
        run: npm ci

      - name: Unit Testleri Çalıştır
        run: npm test

      - name: AWS Credentials Ayarla
        uses: aws-actions/configure-aws-credentials@v2
        with:
          aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          aws-region: eu-west-1

      - name: Staging Deploy
        if: github.ref == 'refs/heads/staging'
        run: |
          npx serverless deploy --stage staging --verbose
          echo "Staging deploy tamamlandı"

      - name: Production Deploy
        if: github.ref == 'refs/heads/main'
        run: |
          npx serverless deploy --stage prod --verbose
          echo "Production deploy tamamlandı"

      - name: Smoke Test
        run: |
          ENDPOINT=$(npx serverless info --stage prod | grep "POST" | awk '{print $2}')
          STATUS=$(curl -s -o /dev/null -w "%{http_code}" -X POST $ENDPOINT/orders 
            -H "Content-Type: application/json" 
            -d '{"userId": "smoke-test", "items": [{"productId": "test", "price": 1, "quantity": 1}]}')
          
          if [ "$STATUS" == "201" ]; then
            echo "Smoke test başarılı: HTTP $STATUS"
          else
            echo "Smoke test başarısız: HTTP $STATUS"
            exit 1
          fi
EOF

echo "Pipeline yapılandırması tamamlandı"

Maliyet Optimizasyonu

Serverless’ın en büyük avantajlarından biri maliyet, ama yanlış yapılandırma faturayı patlatabilir. Şu noktalara dikkat et:

Memory boyutunu optimize et: Lambda’da CPU, memory ile orantılı. 512MB yerine 256MB kullanmak her zaman ucuz değil, bazen daha fazla memory daha hızlı çalıştırır ve toplam maliyet düşer.

Lambda Power Tuning kullan: AWS’nin open source aracı farklı memory konfigürasyonlarını test eder:

# Lambda Power Tuning State Machine çalıştır
aws stepfunctions start-execution 
  --state-machine-arn arn:aws:states:eu-west-1:ACCOUNT_ID:stateMachine:powerTuningMachine 
  --input '{
    "lambdaARN": "arn:aws:lambda:eu-west-1:ACCOUNT_ID:function:ecommerce-platform-prod-createOrder",
    "powerValues": [128, 256, 512, 1024],
    "num": 50,
    "payload": {"userId": "test", "items": [{"productId": "p1", "price": 10, "quantity": 1}]},
    "parallelInvocation": true,
    "strategy": "cost"
  }'

# Reserved Concurrency ayarla - sınırsız scale'i engelle
aws lambda put-function-concurrency 
  --function-name ecommerce-platform-prod-createOrder 
  --reserved-concurrent-executions 100

echo "Maliyet optimizasyonu ayarları tamamlandı"

DynamoDB on-demand billing: Tahmin edilemeyen workload için on-demand, sabit yük için provisioned kullan.

S3 yerine EFS değil: Lambda’da büyük dosya işlemleri için S3 kullan, EFS ekstra maliyet getirir.

Log retention süresi: CloudWatch Logs’u sonsuz tutma, 30-90 gün yeterli.

Yaygın Hatalar ve Çözümleri

Serverless projelerinde sık karşılaştığım hataları özetleyeyim:

Connection pool problemi: Her Lambda invocation’ında yeni DB connection açmak hem yavaş hem pahalı. Connection’ı handler dışında tanımla, warm start’larda yeniden kullanılır.

Timeout yönetimi: Lambda timeout’u SQS visibility timeout’undan küçük olmalı. 30 saniyelik Lambda için en az 35 saniye visibility timeout ayarla.

Circular dependency: Servisler birbirini doğrudan çağırırsa tightly coupled olur. Her zaman event bus üzerinden haberleşin.

Environment variable limiti: Lambda’da 4KB environment variable limiti var. Büyük konfigürasyonları SSM Parameter Store’dan çek.

Bundle size: Node.js’te tüm node_modules’u pakete dahil etme. Tree shaking ve sadece gerekli modülleri import et. Paket boyutu 50MB’ı geçmemeli.

Sonuç

Serverless ve mikroservis mimarisini birleştirmek, doğru yapıldığında gerçekten güçlü bir sistem ortaya çıkarıyor. Özellikle e-ticaret, fintech ve SaaS ürünlerinde bu hibrit yaklaşım hem geliştirici verimliliğini artırıyor hem de operasyonel yükü azaltıyor.

Ama dikkat etmen gereken şey şu: Her şeyi serverless yapma hevesine kapılma. Sürekli çalışan, düşük latency gerektiren ve stateful olan iş yükleri için container tabanlı servisler hala daha uygun. Billing sistemi, authentication servisi, gerçek zamanlı WebSocket bağlantıları bunlara örnek verilebilir.

Doğru yaklaşım şu soruları sormak: Bu iş yükü ne sıklıkla çalışıyor? Latency toleransı nedir? State tutuyor mu? Cevaplara göre serverless mu container mi sorusu kendiliğinden cevap buluyor.

Production’a geçmeden önce mutlaka Load testing yap, DLQ’ları konfigüre et, CloudWatch alarm’larını kur ve maliyet tahminini hesapla. Serverless’ın “sihirli çözüm” olmadığını, sadece doğru araç için doğru yerde kullanıldığında değer yarattığını aklında tut.

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir