Lambda
08 / 08

Deployment, Monitoring & Interview Questions

Lambda: Deployment, Monitoring & Interview Questions

Deployment Methods

# ZIP deployment (for code <250MB unzipped)
zip -r function.zip . --exclude "*.test.js" "node_modules/.cache/*"
aws lambda update-function-code \
  --function-name my-api-handler \
  --zip-file fileb://function.zip

# Container image deployment (up to 10GB)
# Build and push to ECR
aws ecr get-login-password --region eu-west-1 | \
  docker login --username AWS --password-stdin 123456789012.dkr.ecr.eu-west-1.amazonaws.com

docker build -t my-lambda .
docker tag my-lambda:latest 123456789012.dkr.ecr.eu-west-1.amazonaws.com/my-lambda:latest
docker push 123456789012.dkr.ecr.eu-west-1.amazonaws.com/my-lambda:latest

# Update function to use new image
aws lambda update-function-code \
  --function-name my-api-handler \
  --image-uri 123456789012.dkr.ecr.eu-west-1.amazonaws.com/my-lambda:latest

Versions & Aliases

# Publish immutable version
aws lambda publish-version --function-name my-api-handler
# Returns version number (e.g., 7)

# Create alias pointing to version
aws lambda create-alias \
  --function-name my-api-handler \
  --name production \
  --function-version 7

# Canary deployment: 10% to new version, 90% to old
aws lambda update-alias \
  --function-name my-api-handler \
  --name production \
  --function-version 8 \
  --routing-config AdditionalVersionWeights={"7"=0.9}

# After validation: cut over to 100%
aws lambda update-alias \
  --function-name my-api-handler \
  --name production \
  --function-version 8

SAM (Serverless Application Model)

# template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31

Globals:
  Function:
    Runtime: nodejs20.x
    MemorySize: 512
    Timeout: 30
    Environment:
      Variables:
        NODE_ENV: production

Resources:
  ApiHandler:
    Type: AWS::Serverless::Function
    Properties:
      Handler: dist/index.handler
      CodeUri: .
      Architectures: [arm64]
      Events:
        Api:
          Type: HttpApi
          Properties:
            Path: /{proxy+}
            Method: ANY
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref UsersTable

  UsersTable:
    Type: AWS::DynamoDB::Table
    Properties:
      BillingMode: PAY_PER_REQUEST
      AttributeDefinitions:
        - AttributeName: pk
          AttributeType: S
      KeySchema:
        - AttributeName: pk
          KeyType: HASH
# SAM CLI workflow
sam build
sam local invoke ApiHandler --event events/test.json   # Local testing
sam local start-api                                     # Local HTTP server
sam deploy --guided                                     # First deploy
sam deploy                                              # Subsequent deploys

CloudWatch Logs & Monitoring

# Lambda auto-creates log group: /aws/lambda/function-name
# Tail live logs
aws logs tail /aws/lambda/my-api-handler --follow

# Query with Insights
aws logs start-query \
  --log-group-name /aws/lambda/my-api-handler \
  --start-time $(date -d '1 hour ago' +%s) \
  --end-time $(date +%s) \
  --query-string 'fields @timestamp, @message
    | filter @message like /ERROR/
    | sort @timestamp desc
    | limit 50'
// Structured logging (JSON for CloudWatch Insights queries)
export const handler = async (event, context) => {
  const log = (level, msg, data = {}) => console.log(JSON.stringify({
    level, msg, requestId: context.awsRequestId, ...data
  }));

  log('info', 'Processing request', { path: event.rawPath });

  try {
    const result = await processRequest(event);
    log('info', 'Request completed', { durationMs: /* ... */ 0 });
    return result;
  } catch (err) {
    log('error', 'Request failed', { error: err.message, stack: err.stack });
    throw err;
  }
};

X-Ray Tracing

# Enable active tracing
aws lambda update-function-configuration \
  --function-name my-api-handler \
  --tracing-config Mode=Active
// Instrument AWS SDK calls automatically via X-Ray
import AWSXRay from 'aws-xray-sdk-core';
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';

// Wrap client to trace all calls
const ddbClient = AWSXRay.captureAWSv3Client(new DynamoDBClient({}));

Interview Questions

  • When NOT to use Lambda? Long-running tasks >15 min; stateful workloads; cold start latency is unacceptable; need full OS/GPU access; very high sustained throughput where EC2/containers are cheaper

  • How to handle Lambda cold starts? Provisioned Concurrency for latency-sensitive; SnapStart for Java; minimize package size; init clients outside handler; consider ARM64

  • Lambda vs Fargate? Lambda: event-driven, max 15min, simpler ops. Fargate: containerized, long-running, more control over runtime

  • How does Lambda scale? Automatically — one concurrent execution per request. Burst limit applies (initial scaling speed is capped per region). Reserved concurrency limits max scale.

  • How to make Lambda idempotent? Include idempotency key in requests; check if already processed (DynamoDB conditional writes); use Powertools Idempotency utility

  • Lambda and VPC? Putting Lambda in VPC adds cold start latency (ENI provisioning). Required for RDS access. Use RDS Proxy to reduce connection pressure. VPC Lambda needs NAT Gateway for internet access.

  • How is Lambda priced? Requests ($0.20/million) + Duration (GB-seconds, $0.0000166667 per GB-second). Provisioned Concurrency charged separately per GB-hour.

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free