How to Deploy Serverless Applications Using AWS Lambda and CDK

Deploy serverless applications using AWS Lambda and CDK by defining your handler as a construct, adding supporting resources like API Gateway, iterating with cdk watch for fast development, and promoting to production via cdk deploy with full CloudFormation safety checks.

The aws/agent-toolkit-for-aws repository provides comprehensive guidance for building production-grade serverless architectures. According to the source code in skills/core-skills/aws-serverless/references/deployment.md, deploying AWS Lambda functions through the AWS Cloud Development Kit (CDK) follows a declarative, infrastructure-as-code pattern that automates packaging, permission management, and API integration.

Architectural Overview of CDK Serverless Deployment

Deploying serverless workloads with CDK creates a repeatable pipeline that bridges development velocity with operational safety. The architecture centers on constructs—pre-configured cloud components that encapsulate AWS best practices.

The deployment flow implemented in the agent-toolkit follows five stages:

  1. Define Lambda handlers using language-specific constructs (NodejsFunction or PythonFunction) that automatically bundle dependencies.
  2. Attach supporting resources such as DynamoDB tables, S3 buckets, or HTTP APIs via L2 constructs that apply least-privilege IAM permissions automatically.
  3. Synthesize the CloudFormation template locally using cdk synth to validate infrastructure changes.
  4. Iterate rapidly during development with hotswap deployments (cdk deploy --hotswap) or continuous watching (cdk watch).
  5. Deploy to production using standard cdk deploy commands that leverage CloudFormation's atomic updates and rollback capabilities.

Essential CDK Constructs for Lambda Serverless Applications

The aws/agent-toolkit-for-aws repository defines specific construct patterns in skills/core-skills/aws-serverless/references/lambda.md and skills/core-skills/aws-serverless/references/deployment.md.

NodejsFunction for TypeScript and JavaScript

The NodejsFunction construct from aws-cdk-lib/aws-lambda-nodejs bundles Node.js handlers using esbuild automatically, eliminating manual webpack configuration.

import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';

const fn = new NodejsFunction(this, 'MyFunction', {
  entry: 'src/handler.ts',
  runtime: cdk.aws_lambda.Runtime.NODEJS_22_X,
});

PythonFunction for Python Runtimes

For Python workloads, the PythonFunction construct (available in the alpha module @aws-cdk/aws-lambda-python-alpha) handles dependency resolution via Docker-based bundling.

import aws_lambda_python_alpha as lambda_python

fn = lambda_python.PythonFunction(
    self, "MyFunction",
    entry="src",
    runtime=lambda_python.Runtime.PYTHON_3_11,
)

HttpApi and HttpLambdaIntegration for API Frontends

To expose Lambda functions via HTTP endpoints, combine HttpApi (from aws-cdk-lib/aws-apigatewayv2) with HttpLambdaIntegration (from aws-cdk-lib/aws-apigatewayv2-integrations):

import * as apigw from 'aws-cdk-lib/aws-apigatewayv2';
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';

const api = new apigw.HttpApi(this, 'HttpApi', {
  corsPreflight: {
    allowHeaders: ['Content-Type'],
    allowMethods: [apigw.CorsHttpMethod.GET, apigw.CorsHttpMethod.POST],
    allowOrigins: ['*'],
  },
});

api.addRoutes({
  path: '/{proxy+}',
  methods: [apigw.HttpMethod.ANY],
  integration: new HttpLambdaIntegration('LambdaIntegration', fn),
});

Fast Iteration with CDK Watch and Hotswap

Development velocity relies on minimizing deployment latency. The agent-toolkit documentation in skills/core-skills/aws-serverless/references/deployment.md outlines two mechanisms for accelerating the inner loop:

  • cdk deploy --hotswap: Updates Lambda code and configuration directly without invoking CloudFormation, reducing deployment time from minutes to seconds.
  • cdk watch: Monitors source files continuously and automatically triggers hotswap deployments when changes are detected.

For safety, combine these with fallback options:


# Continuous development mode

cdk watch

# One-off fast update with CloudFormation fallback

cdk deploy --hotswap-fallback

Warning: Hotswap bypasses CloudFormation drift detection and safety checks. Never use --hotswap in production environments; reserve it strictly for local development iterations.

Step-by-Step Deployment Workflow

Before deploying serverless applications using AWS Lambda and CDK, ensure your target account is bootstrapped. The following workflow reflects the commands documented in skills/core-skills/aws-cdk/references/bootstrap-and-project-setup.md:


# 1. Bootstrap (one-time per account/region)

cdk bootstrap aws://123456789012/us-east-1

# 2. Validate infrastructure synthesis

cdk synth

# 3. Development iteration loop

cdk watch

# 4. Production deployment

cdk deploy

The bootstrap process provisions an S3 bucket and IAM roles required for CloudFormation asset staging, which cdk deploy relies on for packaging Lambda artifacts.

Complete Implementation Examples

TypeScript Node.js Serverless Stack

This complete example from the agent-toolkit patterns combines NodejsFunction with HTTP API integration:

#!/usr/bin/env node
import * as cdk from 'aws-cdk-lib';
import { NodejsFunction } from 'aws-cdk-lib/aws-lambda-nodejs';
import * as apigw from 'aws-cdk-lib/aws-apigatewayv2';
import { HttpLambdaIntegration } from 'aws-cdk-lib/aws-apigatewayv2-integrations';
import { ServerlessAppStack } from '../lib/serverless-app-stack';

class ServerlessAppStack extends cdk.Stack {
  constructor(scope: cdk.App, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const fn = new NodejsFunction(this, 'MyFunction', {
      entry: 'src/handler.ts',
      runtime: cdk.aws_lambda.Runtime.NODEJS_22_X,
    });

    const api = new apigw.HttpApi(this, 'HttpApi', {
      corsPreflight: {
        allowHeaders: ['Content-Type'],
        allowMethods: [apigw.CorsHttpMethod.GET, apigw.CorsHttpMethod.POST],
        allowOrigins: ['*'],
      },
    });

    api.addRoutes({
      path: '/{proxy+}',
      methods: [apigw.HttpMethod.ANY],
      integration: new HttpLambdaIntegration('LambdaIntegration', fn),
    });
  }
}

const app = new cdk.App();
new ServerlessAppStack(app, 'ServerlessAppStack');

Python Serverless Implementation

For Python developers, the equivalent implementation uses constructs from aws-cdk-lib/aws-lambda-python-alpha:

from aws_cdk import (
    Stack,
    aws_lambda_python_alpha as lambda_python,
    aws_apigatewayv2 as apigw,
    aws_apigatewayv2_integrations as integrations,
)
from constructs import Construct

class ServerlessAppStack(Stack):
    def __init__(self, scope: Construct, id: str, **kwargs):
        super().__init__(scope, id, **kwargs)
        
        fn = lambda_python.PythonFunction(
            self, "MyFunction",
            entry="src",
            runtime=lambda_python.Runtime.PYTHON_3_11,
        )
        
        api = apigw.HttpApi(self, "HttpApi")
        api.add_routes(
            path="/{proxy+}",
            methods=[apigw.HttpMethod.ANY],
            integration=integrations.HttpLambdaIntegration("LambdaIntegration", fn),
        )

Production Deployment Best Practices

When moving beyond development, follow these patterns documented in skills/core-skills/aws-serverless/references/deployment.md and skills/core-skills/aws-cdk/SKILL.md:

  • Apply least-privilege IAM permissions: Use construct grant* methods (e.g., bucket.grantReadWrite(fn)) instead of manual policy statements. CDK L2 constructs automatically generate minimal required permissions.
  • Implement versioning and aliases: Deploy Lambda versions explicitly and route traffic via aliases to enable blue/green deployments and instant rollbacks.
  • Enable observability: Activate X-Ray tracing (Tracing.ACTIVE) and configure CloudWatch Logs retention explicitly using cdk.Duration.days(30).
  • Detect drift: Periodically run cdk diff against deployed stacks to identify manual console changes that violate infrastructure-as-code policies.
  • Automate via CI/CD: Integrate cdk synth, cdk diff, and cdk deploy into deployment pipelines (GitHub Actions, AWS CodePipeline) with approval gates before production stages.

Summary

  • Define Lambda handlers using NodejsFunction or PythonFunction constructs to automate dependency bundling and runtime configuration.
  • Accelerate development with cdk watch and cdk deploy --hotswap, but restrict these to local development only.
  • Bootstrap accounts once per region using cdk bootstrap before attempting initial deployments.
  • Grant permissions via construct methods (e.g., table.grantReadData(fn)) to maintain least-privilege security postures automatically.
  • Deploy to production using standard cdk deploy to ensure CloudFormation manages atomic updates, rollback capabilities, and drift detection.

Frequently Asked Questions

What is the difference between cdk deploy and cdk deploy --hotswap?

cdk deploy performs a full CloudFormation deployment, creating change sets, validating resources, and enabling automatic rollback on failure. In contrast, cdk deploy --hotswap bypasses CloudFormation for Lambda code updates, directly modifying the function code in seconds. According to skills/core-skills/aws-serverless/references/deployment.md, hotswap is intended only for development because it skips safety checks and can create infrastructure drift.

Do I need to bootstrap my AWS account before deploying serverless applications?

Yes. The cdk bootstrap command provisions an S3 bucket and IAM execution roles required for staging Lambda deployment packages and CloudFormation templates. As documented in skills/core-skills/aws-cdk/references/bootstrap-and-project-setup.md, bootstrapping is a one-time requirement per AWS account and region before running cdk deploy for the first time.

Which construct should I use for Python Lambda functions?

Use PythonFunction from the @aws-cdk/aws-lambda-python-alpha module. This construct automatically handles dependency installation using a Docker-based bundling process, packaging your Python handler and requirements.txt dependencies into the deployment artifact without manual intervention.

How do I enable hot reloading during development?

Run cdk watch from your project root. This command monitors your source files and automatically executes cdk deploy --hotswap when changes are detected, providing sub-second feedback loops for Lambda code modifications. For even faster iterations, ensure your IDE saves files automatically and verify that your cdk.json includes the appropriate watch paths.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →