Panduan Praktis AWS Lambda dengan Claude Code: Node.js, IAM, API Gateway
Buat Lambda Node.js dengan Claude Code: tes lokal, IAM least privilege, environment variables, API Gateway, dan logs.
Claude Code sangat membantu untuk AWS Lambda karena bisa menyiapkan handler, event fixture, draft policy IAM, command deploy, dan checklist review dalam satu konteks. Kecepatan ini berguna, tetapi permission dan biaya AWS adalah keputusan produksi. Gunakan Claude Code untuk membuat draft dan memeriksa risiko, bukan untuk memberi permission, membuka API publik, atau membuat resource berbayar tanpa review manusia.
Panduan ini memakai alur yang cocok untuk tim: membuat Lambda Node.js, mengetes secara lokal, menjaga IAM tetap dekat dengan least privilege, mengatur environment variables, menghubungkan API Gateway, membaca CloudWatch Logs, mengupdate zip package, dan menjalankan review loop yang aman. Lambda adalah runtime kecil yang berjalan saat event datang. IAM menentukan apa yang boleh dilakukan function. API Gateway adalah pintu HTTP yang meneruskan request ke Lambda.
Sebelum implementasi, buka referensi resmi: AWS Lambda getting started, Lambda dengan Node.js, environment variables Lambda, monitoring CloudWatch Logs, dan Claude Code common workflows. Contoh di bawah memakai runtime Lambda Node.js 24 per 1 Juni 2026.
Kapan Pola Ini Cocok
Lambda cocok ketika kamu butuh aksi kecil dan andal tanpa menjalankan server sepanjang hari. Claude Code paling berguna ketika pekerjaan punya struktur berulang dan reviewer tetap memegang keputusan akhir.
| Use case | Mengapa cocok untuk Lambda | Draft dari Claude Code | Review manusia wajib melihat |
|---|---|---|---|
| Webhook receiver | Payment, form, dan event SaaS biasanya singkat | Signature check, event fixture, failure response | Secret, retry, event duplikat |
| API JSON internal | Endpoint kecil tidak butuh app server permanen | Handler, command API Gateway, format log | Auth, CORS, exposure, biaya |
| Entry point batch | CSV, image job, notifikasi bisa dimulai kecil | Input validation, structured log, error class | Timeout, retry strategy, safe deletion |
Untuk proof of concept pertama, AWS CLI plus zip package cukup cepat. Untuk operasi tim, pindahkan logic yang sama ke SAM, CDK, atau workflow IaC lain yang direview.
| Metode | Cocok untuk | Perhatikan |
|---|---|---|
| AWS Console | Cek behavior sekali | Langkah manual tidak tersimpan rapi untuk review |
| AWS CLI + zip | Proof kecil yang reproducible | IAM dan env vars harus direview hati-hati |
| SAM / CDK | Operasi tim jangka panjang | Review IaC dan approval deploy wajib ada |
flowchart LR
A[Draft dengan Claude Code] --> B[Tes lokal Node.js]
B --> C[Manusia review IAM dan environment]
C --> D[Deploy zip package ke dev]
D --> E[Test lewat API Gateway]
E --> F[Baca CloudWatch Logs]
F --> A
1. Buat Handler Node.js Lambda
Mulai dengan index.mjs tanpa dependency eksternal. File ini menerima event HTTP API v2 dan format REST API yang lebih lama.
// index.mjs
import crypto from "node:crypto";
const allowedStages = new Set(["dev", "staging", "prod"]);
function readConfig() {
const stage = process.env.APP_STAGE ?? "dev";
if (!allowedStages.has(stage)) {
throw new Error(`Invalid APP_STAGE: ${stage}`);
}
return {
stage,
tableName: process.env.TABLE_NAME ?? "local-orders",
logLevel: process.env.LOG_LEVEL ?? "info",
};
}
function log(level, message, details = {}) {
console.log(
JSON.stringify({
level,
message,
service: "orders-api",
...details,
})
);
}
function json(statusCode, body) {
return {
statusCode,
headers: {
"content-type": "application/json",
},
body: JSON.stringify(body),
};
}
function parseBody(event) {
if (!event.body) return {};
const raw = event.isBase64Encoded
? Buffer.from(event.body, "base64").toString("utf8")
: event.body;
return JSON.parse(raw);
}
export async function handler(event = {}, context = {}) {
const config = readConfig();
const method = event.requestContext?.http?.method ?? event.httpMethod ?? "GET";
const path = event.rawPath ?? event.path ?? "/";
const requestId = context.awsRequestId ?? "local";
log("info", "request.start", {
requestId,
method,
path,
stage: config.stage,
});
try {
if (method === "GET" && path === "/health") {
return json(200, { ok: true, stage: config.stage });
}
if (method === "POST" && path === "/orders") {
const payload = parseBody(event);
const orderId = payload.orderId ?? crypto.randomUUID();
log("info", "order.accepted", {
requestId,
orderId,
tableName: config.tableName,
});
return json(202, {
orderId,
status: "accepted",
storedIn: config.tableName,
});
}
return json(404, { error: "not_found", method, path });
} catch (error) {
log("error", "request.failed", {
requestId,
errorName: error.name,
errorMessage: error.message,
});
return json(500, { error: "internal_error", requestId });
}
}
Versi pertama ini belum menulis ke DynamoDB. Itu sengaja. Untuk pemula, milestone pertama adalah menerima event, parse JSON, mengembalikan response valid, dan menghasilkan log yang mudah dicari. Database dan permission tambahan sebaiknya masuk setelah dasar ini stabil.
2. Tes Lokal dengan Event Fixture
Fixture adalah input test yang disimpan. Walaupun dibuat oleh Claude Code, simpan di repository supaya reviewer bisa mereproduksi masalah.
{
"version": "2.0",
"routeKey": "POST /orders",
"rawPath": "/orders",
"requestContext": {
"http": {
"method": "POST",
"path": "/orders"
}
},
"headers": {
"content-type": "application/json"
},
"body": "{\"orderId\":\"demo-1001\",\"amount\":3200,\"currency\":\"JPY\"}",
"isBase64Encoded": false
}
Simpan sebagai events/create-order.json, lalu tambahkan runner lokal.
// local-test.mjs
import { readFile } from "node:fs/promises";
import { handler } from "./index.mjs";
process.env.APP_STAGE = "dev";
process.env.TABLE_NAME = "orders-dev";
process.env.LOG_LEVEL = "debug";
const eventPath = process.argv[2] ?? "events/create-order.json";
const event = JSON.parse(await readFile(eventPath, "utf8"));
const result = await handler(event, { awsRequestId: "local-001" });
console.log(JSON.stringify(result, null, 2));
Jalankan sebelum menyentuh AWS:
node local-test.mjs events/create-order.json
Jika hasil lokal tidak mengembalikan statusCode: 202, deploy hanya membuat debugging lebih lambat. Fixture konkret juga membantu Claude Code menganalisis input nyata, bukan menebak-nebak.
3. Jaga IAM Dekat dengan Least Privilege
Jangan pasang AdministratorAccess ke execution role Lambda. Mulai dari permission logs, lalu tambahkan akses data hanya saat handler benar-benar memerlukannya.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "CreateOwnLogGroupIfMissing",
"Effect": "Allow",
"Action": "logs:CreateLogGroup",
"Resource": "arn:aws:logs:ap-northeast-1:123456789012:*"
},
{
"Sid": "WriteOwnLambdaLogs",
"Effect": "Allow",
"Action": ["logs:CreateLogStream", "logs:PutLogEvents"],
"Resource": "arn:aws:logs:ap-northeast-1:123456789012:log-group:/aws/lambda/claude-orders-dev:*"
},
{
"Sid": "ReadWriteOnlyOrdersTable",
"Effect": "Allow",
"Action": ["dynamodb:GetItem", "dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:Query"],
"Resource": "arn:aws:dynamodb:ap-northeast-1:123456789012:table/orders-dev"
}
]
}
Anggap JSON ini sebagai draft, bukan jawaban production. Ganti account, region, function name, dan table name. Hapus blok DynamoDB sampai benar-benar dipakai. Untuk review permission yang lebih dalam, baca juga panduan AWS IAM.
4. Deploy Zip Package dengan AWS CLI
Command berikut membuat resource AWS nyata dan bisa menimbulkan biaya. Gunakan akun dev, cek region, dan pahami cleanup sebelum menjalankan.
export AWS_REGION=ap-northeast-1
export FUNCTION_NAME=claude-orders-dev
export ROLE_NAME=claude-orders-dev-lambda-role
export ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
zip function.zip index.mjs
Buat trust-policy.json agar Lambda bisa assume role tersebut.
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": "lambda.amazonaws.com"
},
"Action": "sts:AssumeRole"
}
]
}
Simpan draft IAM sebelumnya sebagai lambda-policy.json, lalu buat role dan function.
aws iam create-role \
--role-name "$ROLE_NAME" \
--assume-role-policy-document file://trust-policy.json
aws iam put-role-policy \
--role-name "$ROLE_NAME" \
--policy-name claude-orders-dev-inline \
--policy-document file://lambda-policy.json
ROLE_ARN=$(aws iam get-role \
--role-name "$ROLE_NAME" \
--query "Role.Arn" \
--output text)
aws lambda create-function \
--function-name "$FUNCTION_NAME" \
--runtime nodejs24.x \
--handler index.handler \
--zip-file fileb://function.zip \
--role "$ROLE_ARN" \
--architectures arm64 \
--timeout 10 \
--memory-size 128 \
--environment "Variables={APP_STAGE=dev,TABLE_NAME=orders-dev,LOG_LEVEL=info}" \
--region "$AWS_REGION"
Untuk update kode saja, tidak perlu membuat ulang function.
zip function.zip index.mjs
aws lambda update-function-code \
--function-name "$FUNCTION_NAME" \
--zip-file fileb://function.zip \
--region "$AWS_REGION"
Hati-hati dengan environment variables. Saat memakai update-function-configuration, map Variables diganti seluruhnya. Ambil konfigurasi sekarang sebelum mengubah. Password dan API key sebaiknya masuk ke Secrets Manager atau Parameter Store, bukan environment variable biasa.
aws lambda update-function-configuration \
--function-name "$FUNCTION_NAME" \
--environment "Variables={APP_STAGE=dev,TABLE_NAME=orders-dev,LOG_LEVEL=debug}" \
--region "$AWS_REGION"
5. Verifikasi API Gateway dan CloudWatch Logs
Invoke Lambda secara langsung dulu.
aws lambda invoke \
--function-name "$FUNCTION_NAME" \
--payload fileb://events/create-order.json \
--region "$AWS_REGION" \
response.json
cat response.json
Lalu buat HTTP API. Ini menghasilkan public endpoint, jadi review auth, CORS, rate limit, dan rencana deletion sebelum menjalankan.
API_ID=$(aws apigatewayv2 create-api \
--name claude-orders-dev-api \
--protocol-type HTTP \
--target "arn:aws:lambda:${AWS_REGION}:${ACCOUNT_ID}:function:${FUNCTION_NAME}" \
--query "ApiId" \
--output text)
aws lambda add-permission \
--function-name "$FUNCTION_NAME" \
--statement-id AllowHttpApiInvoke \
--action lambda:InvokeFunction \
--principal apigateway.amazonaws.com \
--source-arn "arn:aws:execute-api:${AWS_REGION}:${ACCOUNT_ID}:${API_ID}/*/*" \
--region "$AWS_REGION"
API_ENDPOINT=$(aws apigatewayv2 get-api \
--api-id "$API_ID" \
--query "ApiEndpoint" \
--output text)
curl -s "$API_ENDPOINT/health"
curl -s -X POST "$API_ENDPOINT/orders" \
-H "content-type: application/json" \
-d '{"amount":3200,"currency":"JPY"}'
Baca logs segera setelah testing.
aws logs tail "/aws/lambda/${FUNCTION_NAME}" \
--follow \
--region "$AWS_REGION"
Jika logs tidak muncul, cek region, function name, logs:CreateLogStream, dan logs:PutLogEvents. Jika API Gateway mengembalikan 500, pastikan response Lambda memiliki statusCode, headers, dan body. Untuk detail lanjutan, baca panduan AWS CloudWatch dan panduan AWS API Gateway.
Prompt Claude untuk Review Lambda
Minta Claude Code menjelaskan risiko sebelum mengedit atau deploy.
You are reviewing a Node.js AWS Lambda change for a team repository.
Scope:
- Files: index.mjs, events/*.json, IAM policy JSON, deployment commands in docs
- Runtime: nodejs24.x
- Entry point: index.handler
Review for:
1. API Gateway event compatibility and response shape
2. Input validation and JSON parsing failures
3. Environment variables that overwrite existing values
4. IAM actions that are wider than needed
5. CloudWatch logs that expose secrets or personal data
6. AWS resources that can create unexpected cost
7. Local test commands that a reviewer can copy and run
Return:
- blocking issues
- non-blocking improvements
- exact commands to verify locally
- questions a human must answer before deploying
Loop yang aman adalah: explore, plan, edit, test lokal, deploy hanya ke dev, baca logs, lalu minta approval manusia untuk IAM dan biaya. Untuk membawa proof of concept ini ke CI/CD dan IaC, lanjutkan ke panduan deployment AWS.
Kesalahan yang Sering Terjadi
Pertama, deploy sebelum reproduksi lokal. Jika bentuk event salah, fixture menemukannya lebih cepat daripada CloudWatch.
Kedua, menyimpan secret langsung di environment variables. Environment variables cocok untuk konfigurasi, tetapi secret butuh access control dan rotasi.
Ketiga, IAM terlalu lebar. dynamodb:* dan Resource: "*" membuat demo cepat berhasil, tetapi memperbesar dampak kesalahan.
Keempat, membuka endpoint API Gateway tanpa owner yang jelas. Sebelum membagikan URL, tentukan auth, CORS, throttling, logging, dan cleanup date.
Kelima, mengabaikan biaya. Lambda terlihat kecil, tetapi API Gateway, CloudWatch Logs, DynamoDB, NAT, dan external API calls bisa menimbulkan charge.
ClaudeCodeLab merapikan workflow seperti ini dalam Claude Code templates and training material. Jika tim kamu ingin merancang AWS permissions, CLAUDE.md, review prompts, dan aturan approval deploy untuk repository nyata, lihat Claude Code consultation and training.
Hapus resource proof of concept setelah selesai.
aws apigatewayv2 delete-api --api-id "$API_ID" --region "$AWS_REGION"
aws lambda delete-function --function-name "$FUNCTION_NAME" --region "$AWS_REGION"
aws iam delete-role-policy --role-name "$ROLE_NAME" --policy-name claude-orders-dev-inline
aws iam delete-role --role-name "$ROLE_NAME"
Setelah mencoba workflow di artikel ini, manfaat paling besar adalah Claude Code menjaga handler, fixture, draft IAM, dan command CLI dalam satu konteks yang bisa direview. Bagian yang berbahaya bukan sekadar code generation, melainkan keputusan permission dan exposure. Pola yang lebih aman adalah fixture lokal dulu, deploy ke dev, baca bukti CloudWatch, lalu review manusia untuk IAM dan biaya sebelum masuk production.
PDF gratis: cheatsheet Claude Code
Masukkan email dan unduh satu halaman berisi command, kebiasaan review, dan workflow aman.
Kami menjaga datamu dan tidak mengirim spam.
Tentang penulis
Masa
Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.
Artikel terkait
Workflow Obsidian ke CLAUDE.md untuk Claude Code
Ubah catatan kerja Obsidian menjadi operating note CLAUDE.md agar konteks tidak dijelaskan ulang.
Claude Code Revenue CTA Routing: dari artikel ke PDF, Gumroad, dan konsultasi
Workflow Claude Code untuk mengarahkan pembaca ke PDF gratis, Gumroad, atau konsultasi sesuai intent.
Aturan handoff tim Claude Code: bukti review, permission, rollback, dan jalur revenue
Format handoff Claude Code untuk tim: bukti, permission rule, rollback, PDF gratis, Gumroad, dan konsultasi.