Skip to content

Homepage

AWS Lambda Handler Cookbook - A Serverless Service Blueprint

AWS Lambda Handler Cookbook

AWS Recommendation

This repository was recommended in an AWS blog post Best practices for accelerating development with serverless blueprints

aws article

Concepts

I spoke at AWS re:invent 2023 with Heitor Lessa, former Chief Architect of Powertools for AWS Lambda about the concepts I implemented in this project.

The Problem

Starting a Serverless service can be overwhelming. You need to figure out many questions and challenges that have nothing to do with your business domain:

  • How to deploy to the cloud? What IAC framework do you choose?
  • How to write a SaaS-oriented CI/CD pipeline? What does it need to contain?
  • How do you handle observability, logging, tracing, metrics?
  • How do you handle testing?

The Solution

This project aims to reduce cognitive load and answer these questions for you by providing a skeleton Python Serverless service blueprint that implements best practices for AWS Lambda, Serverless CI/CD, and AWS CDK in one blueprint project.

Serverless Service - The Order service

flowchart LR
    subgraph AWS["AWS Cloud"]
        subgraph APIGW["API Gateway"]
            REST["REST API<br/>POST /api/orders<br/>GET /api/orders/{id}<br/>GET /api/orders (list)<br/>DELETE /api/orders/{id}"]
        end

        subgraph Security["Security (Production)"]
            WAF["WAF WebACL<br/>AWS Managed Rules"]
        end

        subgraph Compute["Compute"]
            CREATE["Create Order<br/>Lambda Function"]
            GET["Get Order<br/>Lambda Function"]
            DELETE["Delete Order<br/>Lambda Function"]
            LAYER["Lambda Layer<br/>Common Dependencies"]
        end

        subgraph LMI["Lambda Managed Instances (VPC)"]
            LIST_ALIAS["ListOrders Alias: live"]
            LIST["List Orders<br/>Lambda Function"]
            CP["Capacity Provider<br/>EC2 pool, 2 AZs"]
        end

        subgraph Auth["Authentication"]
            COGNITO["Cognito User Pool<br/>group: managers"]
            PRETOKEN["Pre Token Generation<br/>Lambda (adds aud + scopes)"]
        end

        subgraph Config["Configuration"]
            APPCONFIG["AppConfig<br/>Feature Flags"]
        end

        subgraph Storage["Storage"]
            DDB[("DynamoDB<br/>Orders Table")]
            IDEMPOTENCY[("DynamoDB<br/>Idempotency Table")]
        end
    end

    CLIENT((Client)) -.sign in, get token.-> COGNITO
    COGNITO -.-> PRETOKEN
    CLIENT --> WAF
    WAF --> REST
    REST --> CREATE
    REST --> GET
    REST --> DELETE
    REST --> LIST_ALIAS
    LIST_ALIAS --> LIST
    LIST -.runs on.-> CP
    CREATE --> LAYER
    GET --> LAYER
    DELETE --> LAYER
    CREATE --> APPCONFIG
    CREATE --> DDB
    CREATE --> IDEMPOTENCY
    GET --> DDB
    DELETE --> DDB
    LIST --> DDB
    CREATE -.verifies JWT.-> COGNITO
    GET -.verifies JWT.-> COGNITO
    DELETE -.verifies JWT.-> COGNITO
    LIST -.verifies JWT.-> COGNITO

    classDef client fill:#232F3E,stroke:#232F3E,color:#fff
    classDef network fill:#8C4FFF,stroke:#5A30B5,color:#fff
    classDef security fill:#DD344C,stroke:#A3233A,color:#fff
    classDef compute fill:#ED7100,stroke:#B35500,color:#1b1b1b
    classDef database fill:#C925D1,stroke:#8F1A95,color:#fff
    classDef management fill:#E7157B,stroke:#A50F58,color:#fff
    class CLIENT client
    class WAF,COGNITO security
    class REST network
    class CREATE,GET,DELETE,LAYER,LIST,LIST_ALIAS,CP,PRETOKEN compute
    class DDB,IDEMPOTENCY database
    class APPCONFIG management

Click diagram to zoom

  • This project provides a working orders service where customers can create, get, list, and delete orders of items.

  • The project deploys an API GW with AWS Lambda integrations and stores orders data in a DynamoDB table:

    • POST /api/orders/ - Create a new order
    • GET /api/orders/{order_id} - Get an order by ID
    • DELETE /api/orders/{order_id} - Delete an order by ID
    • GET /api/orders/?limit={n}&next_token={cursor} - List orders with pagination, served by an AWS Lambda Managed Instances pool
  • All /api/orders routes require an Amazon Cognito access token (Authorization: Bearer <token>), verified in the Lambdas by the Powertools JWT verifier. Any signed in user can create, get and list orders, deleting an order requires the orders/manage scope (orders-managers group). Orders belong to the user that created them, and users only reach their own orders. /swagger is public. See Authentication & Authorization.

LIST orders via AWS Lambda Managed Instances

The GET /api/orders/ endpoint runs on AWS Lambda Managed Instances (LMI) instead of standard Lambda. LMI keeps a warm EC2-backed pool of execution environments inside a private VPC, eliminating cold starts on paginated traffic and letting the function cap concurrency per environment to bound DynamoDB Query pressure. The other CRUD endpoints remain on standard Lambda — LMI is adopted per-function, only where the extra surface area (VPC, capacity provider, alias-based publishing) is justified.

See the Lambda Managed Instances deep-dive for architecture, tuning knobs, and the constraints we hit in production.

Monitoring Design

flowchart TB
    subgraph Monitoring["CloudWatch Monitoring"]
        subgraph Dashboards["Dashboards"]
            HL["High-Level Dashboard<br/>API Gateway Metrics<br/>Business KPIs"]
            LL["Low-Level Dashboard<br/>Lambda Metrics<br/>DynamoDB Metrics"]
        end

        subgraph Alarms["CloudWatch Alarms"]
            API_ALARM["API Gateway Alarms<br/>5XX Errors, Latency"]
            LAMBDA_ALARM["Lambda Alarms<br/>Errors, P90 Latency"]
            DDB_ALARM["DynamoDB Alarms<br/>Throttles, Errors"]
        end
    end

    subgraph Notification["Notification"]
        SNS["SNS Topic<br/>KMS Encrypted"]
    end

    subgraph Resources["Monitored Resources"]
        APIGW["API Gateway"]
        LAMBDA["Lambda Function"]
        DDB["DynamoDB Tables"]
    end

    APIGW --> API_ALARM
    LAMBDA --> LAMBDA_ALARM
    DDB --> DDB_ALARM

    API_ALARM --> SNS
    LAMBDA_ALARM --> SNS
    DDB_ALARM --> SNS

    API_ALARM --> HL
    LAMBDA_ALARM --> LL
    DDB_ALARM --> LL

    classDef network fill:#8C4FFF,stroke:#5A30B5,color:#fff
    classDef compute fill:#ED7100,stroke:#B35500,color:#1b1b1b
    classDef database fill:#C925D1,stroke:#8F1A95,color:#fff
    classDef management fill:#E7157B,stroke:#A50F58,color:#fff
    classDef integration fill:#E7157B,stroke:#A50F58,color:#fff
    class APIGW network
    class LAMBDA compute
    class DDB database
    class HL,LL,API_ALARM,LAMBDA_ALARM,DDB_ALARM management
    class SNS integration

Click diagram to zoom

Features

  • Python Serverless service with a recommended file structure.
  • CDK infrastructure with infrastructure tests and security tests.
  • CI/CD pipelines based on Github actions that deploys to AWS with python linters, complexity checks and style formatters.
  • CI/CD pipeline deploys to dev/staging and production environment with different gates between each environment
  • Makefile for simple developer experience.
  • The AWS Lambda handler embodies Serverless best practices and has all the bells and whistles for a proper production ready handler.
  • AWS Lambda handler uses AWS Lambda Powertools.
  • AWS Lambda handler 3 layer architecture: handler layer, logic layer and data access layer
  • Features flags and configuration based on AWS AppConfig
  • CloudWatch dashboards - High level and low level including CloudWatch alarms
  • Idempotent API
  • Amazon Cognito authentication, verified in the Lambdas by the Powertools JWT verifier: any signed in user can create, get and list orders, deleting requires the orders/manage scope
  • Per-user order ownership: users only get, delete and list their own orders (the access token sub claim is the owner)
  • REST API protected by WAF with four AWS managed rules in production deployment
  • Unit, infrastructure, security, integration and E2E tests.
  • Integration and E2E tests use real Cognito users and real access tokens, created and deleted by the tests
  • Automatically generated OpenAPI endpoint: /swagger with Pydantic schemas for both requests and responses
  • Automated protection against API breaking changes

The GitHub blueprint project can be found at https://github.com/ran-isenberg/aws-lambda-handler-cookbook.

AI-Assisted Development

This project uses AI-DLC (AI-Driven Development Life Cycle) for AI-assisted software development. Learn more about AI-DLC in this blog post.

AI-DLC provides a structured, adaptive workflow for:

  • Requirements Analysis - Intelligent requirements gathering and clarification
  • Architecture Design - AI-assisted architectural decisions
  • Code Generation - Structured code implementation with best practices
  • Testing - Comprehensive test generation and validation

The AI-DLC workflow artifacts are stored in the aidlc-docs/ directory.

Claude Code Project Rules

The repository also ships persistent instructions for Claude Code and other CLAUDE.md-aware AI agents, so generated code follows the project's conventions automatically:

  • CLAUDE.md - project overview, layout, and planning guidelines, loaded every session.
  • .claude/rules/ - topic-scoped rule files that load automatically; path-scoped rules load only when the matching files are edited:
    • makefile.md - the make command reference; always drive tasks through targets.
    • github-actions.md - CI workflows and SHA-pinning of actions.
    • service.md and models.md - handler/logic/dal layering, Powertools, and Pydantic conventions.
    • testing.md - unit, integration, e2e, and infrastructure test patterns.
    • cdk.md - construct and stack structure, and cdk-nag v3 suppression conventions.
    • docs.md - documentation build, markdownlint, and OpenAPI schema sync.
    • security.md, dependencies.md, and git-pr.md - secrets and IAM, dependency management, and Conventional Commits.

Serverless Best Practices

The AWS Lambda handler will implement multiple best practice utilities.

Each utility is implemented when a new blog post is published about that utility.

The utilities cover multiple aspects of a production-ready service, including:

While the code examples are written in Python, the principles are valid to any supported AWS Lambda handler programming language.

License

This library is licensed under the MIT License. See the LICENSE file.