DevOps 6 min read

AWS Lambda Serverless Guide: Build Scalable Applications

Master AWS Lambda for serverless computing. Learn function deployment, API Gateway integration, event triggers, and best practices for production.

MR

Moshiour Rahman

· Updated May 9, 2026

What is AWS Lambda?

AWS Lambda is a serverless compute service that runs your code in response to events. You pay only for the compute time consumed—no servers to manage.

Benefits

TraditionalServerless
Provision serversAuto-scaling
Pay for idle timePay per request
Manage infrastructureFocus on code
Manual scalingInstant scaling

Getting Started

Simple Lambda Function

# lambda_function.py
import json

def lambda_handler(event, context):
    """
    event: Input data (JSON)
    context: Runtime information
    """
    name = event.get('name', 'World')

    return {
        'statusCode': 200,
        'headers': {
            'Content-Type': 'application/json'
        },
        'body': json.dumps({
            'message': f'Hello, {name}!'
        })
    }

Deploy with AWS CLI

# Create deployment package
zip function.zip lambda_function.py

# Create Lambda function
aws lambda create-function \
    --function-name my-function \
    --runtime python3.11 \
    --role arn:aws:iam::123456789:role/lambda-role \
    --handler lambda_function.lambda_handler \
    --zip-file fileb://function.zip

# Invoke function
aws lambda invoke \
    --function-name my-function \
    --payload '{"name": "John"}' \
    response.json

Deploy with Serverless Framework

# serverless.yml
service: my-service

provider:
  name: aws
  runtime: python3.11
  region: us-east-1
  memorySize: 256
  timeout: 30

functions:
  hello:
    handler: handler.hello
    events:
      - http:
          path: /hello
          method: get

  processData:
    handler: handler.process
    events:
      - s3:
          bucket: my-bucket
          event: s3:ObjectCreated:*
npm install -g serverless
serverless deploy

API Gateway Integration

REST API

# handler.py
import json
import boto3
from decimal import Decimal

dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('users')

def get_users(event, context):
    response = table.scan()

    return {
        'statusCode': 200,
        'headers': {'Content-Type': 'application/json'},
        'body': json.dumps(response['Items'], default=str)
    }

def get_user(event, context):
    user_id = event['pathParameters']['id']

    response = table.get_item(Key={'id': user_id})

    if 'Item' not in response:
        return {
            'statusCode': 404,
            'body': json.dumps({'error': 'User not found'})
        }

    return {
        'statusCode': 200,
        'body': json.dumps(response['Item'], default=str)
    }

def create_user(event, context):
    body = json.loads(event['body'])

    item = {
        'id': str(uuid.uuid4()),
        'name': body['name'],
        'email': body['email'],
        'created_at': datetime.now().isoformat()
    }

    table.put_item(Item=item)

    return {
        'statusCode': 201,
        'body': json.dumps(item)
    }
# serverless.yml
functions:
  getUsers:
    handler: handler.get_users
    events:
      - http:
          path: /users
          method: get

  getUser:
    handler: handler.get_user
    events:
      - http:
          path: /users/{id}
          method: get

  createUser:
    handler: handler.create_user
    events:
      - http:
          path: /users
          method: post

Request Validation

def create_user(event, context):
    try:
        body = json.loads(event['body'])
    except json.JSONDecodeError:
        return {
            'statusCode': 400,
            'body': json.dumps({'error': 'Invalid JSON'})
        }

    # Validate required fields
    required = ['name', 'email']
    missing = [f for f in required if f not in body]

    if missing:
        return {
            'statusCode': 400,
            'body': json.dumps({
                'error': f'Missing fields: {", ".join(missing)}'
            })
        }

    # Validate email format
    import re
    if not re.match(r'^[\w\.-]+@[\w\.-]+\.\w+$', body['email']):
        return {
            'statusCode': 400,
            'body': json.dumps({'error': 'Invalid email format'})
        }

    # Continue with creation...

Event Sources

S3 Trigger

def process_s3_event(event, context):
    for record in event['Records']:
        bucket = record['s3']['bucket']['name']
        key = record['s3']['object']['key']

        print(f"Processing {key} from {bucket}")

        # Download and process file
        s3 = boto3.client('s3')
        response = s3.get_object(Bucket=bucket, Key=key)
        content = response['Body'].read()

        # Process content...

    return {'statusCode': 200}

SQS Trigger

def process_sqs_messages(event, context):
    for record in event['Records']:
        body = json.loads(record['body'])
        message_id = record['messageId']

        print(f"Processing message {message_id}: {body}")

        # Process message...

    return {'statusCode': 200}

DynamoDB Streams

def process_dynamodb_stream(event, context):
    for record in event['Records']:
        event_name = record['eventName']  # INSERT, MODIFY, REMOVE

        if event_name == 'INSERT':
            new_item = record['dynamodb']['NewImage']
            # Process new item

        elif event_name == 'MODIFY':
            old_item = record['dynamodb']['OldImage']
            new_item = record['dynamodb']['NewImage']
            # Process update

        elif event_name == 'REMOVE':
            old_item = record['dynamodb']['OldImage']
            # Process deletion

    return {'statusCode': 200}

Scheduled Events (Cron)

functions:
  dailyReport:
    handler: handler.daily_report
    events:
      - schedule: cron(0 9 * * ? *)  # 9 AM UTC daily

  hourlyCleanup:
    handler: handler.cleanup
    events:
      - schedule: rate(1 hour)

Layers

Create Layer

# Create layer directory structure
mkdir -p python/lib/python3.11/site-packages

# Install dependencies
pip install requests -t python/lib/python3.11/site-packages/

# Zip layer
zip -r layer.zip python

# Create layer
aws lambda publish-layer-version \
    --layer-name my-dependencies \
    --zip-file fileb://layer.zip \
    --compatible-runtimes python3.11

Use Layer

# serverless.yml
functions:
  myFunction:
    handler: handler.main
    layers:
      - arn:aws:lambda:us-east-1:123456789:layer:my-dependencies:1

Environment Variables

# serverless.yml
provider:
  environment:
    STAGE: ${opt:stage, 'dev'}
    TABLE_NAME: users-${self:provider.stage}

functions:
  myFunction:
    handler: handler.main
    environment:
      SECRET_KEY: ${env:SECRET_KEY}
      API_URL: https://api.example.com
import os

def lambda_handler(event, context):
    table_name = os.environ['TABLE_NAME']
    secret_key = os.environ['SECRET_KEY']
    # Use environment variables...

Cold Starts Optimization

Provisioned Concurrency

functions:
  api:
    handler: handler.api
    provisionedConcurrency: 5

Optimize Imports

# Bad - imports inside handler
def lambda_handler(event, context):
    import boto3
    import pandas as pd  # Slow import

# Good - imports at module level
import boto3
# Initialize outside handler
dynamodb = boto3.resource('dynamodb')
table = dynamodb.Table('my-table')

def lambda_handler(event, context):
    # Handler code
    pass

Connection Reuse

import boto3
from botocore.config import Config

# Reuse connections
config = Config(
    connect_timeout=5,
    read_timeout=30,
    retries={'max_attempts': 3}
)

# Initialize once, reuse across invocations
dynamodb = boto3.resource('dynamodb', config=config)
s3 = boto3.client('s3', config=config)

Error Handling

import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

class ValidationError(Exception):
    pass

def lambda_handler(event, context):
    try:
        # Validate input
        if 'id' not in event:
            raise ValidationError('Missing required field: id')

        # Process
        result = process_data(event)

        return {
            'statusCode': 200,
            'body': json.dumps(result)
        }

    except ValidationError as e:
        logger.warning(f"Validation error: {str(e)}")
        return {
            'statusCode': 400,
            'body': json.dumps({'error': str(e)})
        }

    except Exception as e:
        logger.error(f"Unexpected error: {str(e)}", exc_info=True)
        return {
            'statusCode': 500,
            'body': json.dumps({'error': 'Internal server error'})
        }

Testing

Local Testing

# test_handler.py
import json
from handler import lambda_handler

def test_hello():
    event = {'name': 'John'}
    context = {}

    response = lambda_handler(event, context)

    assert response['statusCode'] == 200
    body = json.loads(response['body'])
    assert body['message'] == 'Hello, John!'

def test_hello_default():
    event = {}
    context = {}

    response = lambda_handler(event, context)

    body = json.loads(response['body'])
    assert body['message'] == 'Hello, World!'

SAM Local

# Install SAM CLI
pip install aws-sam-cli

# Test locally
sam local invoke MyFunction -e event.json

# Start local API
sam local start-api

Monitoring

CloudWatch Logs

import logging

logger = logging.getLogger()
logger.setLevel(logging.INFO)

def lambda_handler(event, context):
    logger.info(f"Request ID: {context.aws_request_id}")
    logger.info(f"Event: {json.dumps(event)}")

    # Your code...

    logger.info(f"Remaining time: {context.get_remaining_time_in_millis()}ms")

X-Ray Tracing

provider:
  tracing:
    lambda: true
    apiGateway: true
from aws_xray_sdk.core import xray_recorder
from aws_xray_sdk.core import patch_all

patch_all()  # Instrument AWS SDK calls

@xray_recorder.capture('process_data')
def process_data(data):
    # Your code...
    pass

Summary

FeatureUse Case
API GatewayREST APIs
S3 TriggerFile processing
SQS TriggerQueue processing
DynamoDB StreamsData sync
ScheduledCron jobs
LayersShared dependencies

AWS Lambda enables building scalable, cost-effective serverless applications.

Is your AI API down right now? Check live status for OpenAI, Claude, Gemini, Groq, and more.
Check status →
MR

Moshiour Rahman

Software Architect & AI Engineer

Share:
MR

Moshiour Rahman

Software Architect & AI Engineer

Enterprise software architect with deep expertise in financial systems, distributed architecture, and AI-powered applications. Building large-scale systems at Fortune 500 companies. Specializing in LLM orchestration, multi-agent systems, and cloud-native solutions. I share battle-tested patterns from real enterprise projects.

Related Articles

Comments

Comments are powered by GitHub Discussions.

Configure Giscus at giscus.app to enable comments.