LangChain Tutorial (TypeScript): deploying to AWS Lambda for advanced developers

By Cyprian AaronsUpdated 2026-04-21
langchaindeploying-to-aws-lambda-for-advanced-developerstypescript

This tutorial shows you how to build a LangChain-based TypeScript Lambda handler, package it for AWS, and keep it stable under cold starts and production constraints. You need this when you want LLM-backed logic behind an API Gateway endpoint without running a long-lived server.

What You'll Need

  • Node.js 20+
  • AWS CLI configured with an IAM user or role that can deploy Lambda
  • An AWS Lambda execution role with:
    • AWSLambdaBasicExecutionRole
    • permission to read any secrets you store in Secrets Manager or SSM
  • A valid OpenAI API key
  • These packages:
    • langchain
    • @langchain/openai
    • aws-lambda
    • esbuild
    • typescript
    • @types/node
  • Basic familiarity with:
    • async/await
    • AWS Lambda handlers
    • API Gateway proxy events

Step-by-Step

  1. Set up the project with TypeScript and the LangChain packages you actually need. For Lambda, keep dependencies lean and compile to a single JS bundle so cold starts stay predictable.
mkdir langchain-lambda && cd langchain-lambda
npm init -y
npm i langchain @langchain/openai aws-lambda
npm i -D typescript esbuild @types/node @types/aws-lambda
npx tsc --init --rootDir src --outDir dist --module commonjs --target es2022 --esModuleInterop true --strict true
mkdir src
  1. Create a small chain that accepts input from the event body and returns structured output. The important part is using a model wrapper from @langchain/openai and keeping prompt construction explicit.
// src/handler.ts
import type { APIGatewayProxyHandlerV2 } from "aws-lambda";
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";

const prompt = ChatPromptTemplate.fromMessages([
  ["system", "You are a concise assistant for insurance operations."],
  ["human", "{question}"],
]);

const model = new ChatOpenAI({
  model: "gpt-4o-mini",
  temperature: 0,
});

export const handler: APIGatewayProxyHandlerV2 = async (event) => {
  const body = event.body ? JSON.parse(event.body) : {};
  const question = String(body.question ?? "").trim();

  if (!question) {
    return { statusCode: 400, body: JSON.stringify({ error: "question is required" }) };
  }

  const chain = prompt.pipe(model);
  const result = await chain.invoke({ question });

  return {
    statusCode: 200,
    headers: { "content-type": "application/json" },
    body: JSON.stringify({ answer: result.content }),
  };
};
  1. Add a build script that bundles everything into one file. Lambda deployment is simpler when you ship a single artifact instead of a node_modules tree full of transitive packages.
{
  "name": "langchain-lambda",
  "version": "1.0.0",
  "private": true,
  "type": "commonjs",
  "scripts": {
    "build": "esbuild src/handler.ts --bundle --platform=node --target=node20 --outfile=dist/index.js",
    "deploy": "npm run build"
  },
  "dependencies": {
    "@langchain/openai": "^0.6.5",
    "aws-lambda": "^1.0.7",
    "langchain": "^0.3.30"
  },
  "devDependencies": {
    "@types/node": "^22.0.0",
    "@types/aws-lambda": "^8.10.147",
    "esbuild": "^0.24.0",
    "typescript": "^5.6.3"
  }
}
  1. Deploy the function with an environment variable for the API key, and give Lambda enough memory to avoid slow model calls plus runtime overhead. If you're using API Gateway, point it at the function URL or integrate through HTTP API later.
npm run build

aws lambda create-function \
  --function-name langchain-ts-demo \
  --runtime nodejs20.x \
  --role arn:aws:iam::123456789012:role/lambda-exec-role \
  --handler index.handler \
  --zip-file fileb://<(cd dist && zip -r ../function.zip .) \
  --timeout 30 \
  --memory-size 512 \
  --environment Variables='{OPENAI_API_KEY=sk-your-key}'
  1. Update the handler for production concerns that matter on Lambda: reuse clients across invocations, avoid per-request initialization, and keep responses deterministic where possible. The code above already creates the model outside the handler, which is the right shape for warm starts.
// src/handler.ts
import type { APIGatewayProxyHandlerV2 } from "aws-lambda";
import { ChatOpenAI } from "@langchain/openai";
import { ChatPromptTemplate } from "@langchain/core/prompts";

const prompt = ChatPromptTemplate.fromMessages([
  ["system", "You are a concise assistant for insurance operations."],
  ["human", "{question}"],
]);

const model = new ChatOpenAI({
	const apiKey = process.env.OPENAI_API_KEY;
	model: "gpt-4o-mini",
	temperature: Number(process.env.TEMPERATURE ?? "0"),
	apiKey,
});

export const handler: APIGatewayProxyHandlerV2 = async (event) => {
	const body = event.body ? JSON.parse(event.body) : {};
	const question = String(body.question ?? "").trim();
	if (!question) return { statusCode: 400, body: JSON.stringify({ error: "question is required" }) };

	const answer = await prompt.pipe(model).invoke({ question });
	return { statusCode: 200, body: JSON.stringify({ answer: answer.content }) };
};

Testing It

Invoke the function with a small JSON payload and verify that you get back a JSON response with an answer field, not an HTML error page or a timeout. If you see question is required, your request format is wrong; if you see auth errors, check the environment variable and IAM role.

Watch CloudWatch Logs for two things:

  • cold start duration on first invocation
  • model latency on subsequent invocations

If latency is unstable, increase memory before touching code; Lambda CPU scales with memory, and LLM orchestration code benefits from that more than people expect.

A good smoke test is to send three requests in a row:

  • empty body → should fail fast with HTTP 400
  • valid question → should return text
  • repeated valid question → should be faster on warm start

Next Steps

  • Add structured output with zod so your Lambda returns validated JSON instead of free-form text.
  • Move secrets to AWS Secrets Manager and load them during initialization.
  • Add API Gateway request validation plus rate limiting before the function gets invoked.

Keep learning

By Cyprian Aarons, AI Consultant at Topiax.

Want the complete 8-step roadmap?

Grab the free AI Agent Starter Kit — architecture templates, compliance checklists, and a 7-email deep-dive course.

Get the Starter Kit

Related Guides