Use Cases (Diperbarui: 2/6/2026)

Claude Code × AWS Lambda Panduan Lengkap | Dari Pembuatan Fungsi hingga Otomatisasi Deployment

Bangun AWS Lambda dengan Claude Code: Node.js 24, SAM, IAM, API Gateway, S3, logs, dan pitfalls nyata.

Claude Code × AWS Lambda Panduan Lengkap | Dari Pembuatan Fungsi hingga Otomatisasi Deployment

Pernahkah Anda mengalami ini saat mengembangkan AWS Lambda? Definisi tipe untuk handler membosankan, harus mencari kebijakan IAM setiap kali, lupa cara menulis template SAM… Claude Code menyelesaikan semua ini sekaligus.

Dari implementasi fungsi Lambda hingga pembuatan kebijakan IAM, pengujian lokal, dan deployment ke produksi — kami membahas setiap langkah pengembangan AWS Lambda super cepat dengan Claude Code menggunakan contoh kode nyata.

Mengapa Claude Code × AWS Lambda?

“Bagian membosankan” dari pengembangan Lambda hampir seluruhnya adalah kode boilerplate.

  • Definisi tipe untuk fungsi handler (APIGatewayProxyHandler, S3Handler …)
  • Penanganan error dan format respons
  • Desain kebijakan IAM dengan hak istimewa minimum
  • Penulisan template SAM / CloudFormation
  • Konfigurasi lingkungan pengujian lokal

Claude Code menghasilkan semua ini dengan satu kalimat seperti “Saya ingin Lambda yang melakukan X”. Dikombinasikan dengan AWS CLI dan SAM CLI, Anda bisa menjalankan semuanya dari pembuatan kode hingga deployment sekaligus.

Pengaturan Lingkungan

# Periksa alat yang diperlukan
aws --version        # AWS CLI v2
sam --version        # SAM CLI 1.100+
node --version       # Node.js 24+

# Konfigurasi kredensial AWS (jika belum dikonfigurasi)
aws configure
# → Access Key ID, Secret Access Key, Region (ap-southeast-1), Output (json)
<!-- Tambahkan ke CLAUDE.md -->
## Konfigurasi AWS
- Region default: ap-southeast-1 (Singapura)
- Runtime Lambda: nodejs24.x
- Alat deployment: AWS SAM
- Direktori sumber: src/functions/
- Template SAM: template.yaml
- Nama stack: my-app-{dev|staging|prod}

## Pedoman Kebijakan IAM
- Terapkan prinsip hak istimewa minimum dengan ketat
- Jangan gunakan wildcard (*)
- Tentukan ARN sumber daya secara konkret

Contoh 1: API Gateway + Lambda (REST API)

Pola paling dasar — Lambda yang menerima permintaan HTTP dan memprosesnya.

Instruksi ke Claude Code

claude -p "
Ketika permintaan GET datang ke /users/{userId},
ambil informasi pengguna dari tabel DynamoDB Users dan kembalikan.
Implementasikan fungsi Lambda dalam TypeScript.

- Runtime: Node.js 24
- Nama tabel: UsersTable (diterima melalui variabel lingkungan)
- Penanganan error: kembalikan respons 404/500 yang sesuai
- Definisi tipe: gunakan @types/aws-lambda
- Output ke: src/functions/getUser/index.ts
"

Implementasi yang Dihasilkan

// src/functions/getUser/index.ts
import {
  APIGatewayProxyHandler,
  APIGatewayProxyResult,
} from "aws-lambda";
import { DynamoDBClient } from "@aws-sdk/client-dynamodb";
import { DynamoDBDocumentClient, GetCommand } from "@aws-sdk/lib-dynamodb";

const client = new DynamoDBClient({ region: process.env.AWS_REGION });
const ddb = DynamoDBDocumentClient.from(client);

const response = (statusCode: number, body: unknown): APIGatewayProxyResult => ({
  statusCode,
  headers: {
    "Content-Type": "application/json",
    "Access-Control-Allow-Origin": "*",
  },
  body: JSON.stringify(body),
});

export const handler: APIGatewayProxyHandler = async (event) => {
  const userId = event.pathParameters?.userId;

  if (!userId) {
    return response(400, { error: "userId is required" });
  }

  try {
    const result = await ddb.send(
      new GetCommand({
        TableName: process.env.USERS_TABLE!,
        Key: { userId },
      })
    );

    if (!result.Item) {
      return response(404, { error: `User '${userId}' not found` });
    }

    return response(200, result.Item);
  } catch (err) {
    console.error("DynamoDB error:", err);
    return response(500, { error: "Internal server error" });
  }
};

Template SAM Juga Dibuat Secara Otomatis

# template.yaml (kutipan)
GetUserFunction:
  Type: AWS::Serverless::Function
  Properties:
    Handler: src/functions/getUser/index.handler
    Runtime: nodejs24.x
    Timeout: 10
    Environment:
      Variables:
        USERS_TABLE: !Ref UsersTable
    Policies:
      - DynamoDBReadPolicy:
          TableName: !Ref UsersTable
    Events:
      GetUserApi:
        Type: Api
        Properties:
          Path: /users/{userId}
          Method: GET

UsersTable:
  Type: AWS::DynamoDB::Table
  Properties:
    TableName: !Sub "${AWS::StackName}-users"
    BillingMode: PAY_PER_REQUEST
    AttributeDefinitions:
      - AttributeName: userId
        AttributeType: S
    KeySchema:
      - AttributeName: userId
        KeyType: HASH

Contoh 2: Lambda dengan Trigger Event S3

Lambda yang dipicu oleh unggahan file untuk menjalankan pemrosesan.

// src/functions/generateThumbnail/index.ts
import { S3Handler } from "aws-lambda";
import { S3Client, GetObjectCommand, PutObjectCommand } from "@aws-sdk/client-s3";
import sharp from "sharp";

const s3 = new S3Client({ region: process.env.AWS_REGION });

export const handler: S3Handler = async (event) => {
  const record = event.Records[0];
  const bucket = record.s3.bucket.name;
  const key = decodeURIComponent(record.s3.object.key.replace(/\+/g, " "));

  // Abaikan prefiks thumbnails/ (cegah infinite loop)
  if (key.startsWith("thumbnails/")) return;

  const { Body } = await s3.send(new GetObjectCommand({ Bucket: bucket, Key: key }));
  const buffer = Buffer.from(await Body!.transformToByteArray());

  const thumbnail = await sharp(buffer)
    .resize(200, 200, { fit: "cover" })
    .webp({ quality: 85 })
    .toBuffer();

  const thumbnailKey = `thumbnails/${key.replace(/\.[^.]+$/, ".webp")}`;
  await s3.send(
    new PutObjectCommand({
      Bucket: bucket,
      Key: thumbnailKey,
      Body: thumbnail,
      ContentType: "image/webp",
    })
  );

  console.log(`Thumbnail dibuat: s3://${bucket}/${thumbnailKey}`);
};

Contoh 3: Lambda Terjadwal (EventBridge)

# Konfigurasi EventBridge di template.yaml
SendReminderFunction:
  Type: AWS::Serverless::Function
  Properties:
    Handler: src/functions/sendReminder/index.handler
    Runtime: nodejs24.x
    Timeout: 300
    Environment:
      Variables:
        DATABASE_URL: !Sub "{{resolve:secretsmanager:${AWS::StackName}/database-url}}"
        RESEND_API_KEY: !Sub "{{resolve:secretsmanager:${AWS::StackName}/resend-api-key}}"
    Events:
      DailyReminder:
        Type: Schedule
        Properties:
          Schedule: cron(0 0 * * ? *)  # UTC 0:00 = WIB 7:00 / WITA 8:00 / WIT 9:00

Minta Claude Code Merancang Kebijakan IAM

claude -p "
Hasilkan kebijakan IAM hak istimewa minimum dalam JSON untuk Lambda yang membutuhkan:
- GetObject dari bucket S3 my-uploads
- PutItem/UpdateItem pada tabel DynamoDB ProcessingJobs
- SendMessage ke antrian SQS ProcessingQueue
- Menulis ke CloudWatch Logs

Simpulkan ARN spesifik dari nama sumber daya yang diberikan.
"
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": ["s3:GetObject"],
      "Resource": "arn:aws:s3:::my-uploads/*"
    },
    {
      "Effect": "Allow",
      "Action": ["dynamodb:PutItem", "dynamodb:UpdateItem"],
      "Resource": "arn:aws:dynamodb:ap-southeast-1:*:table/ProcessingJobs"
    },
    {
      "Effect": "Allow",
      "Action": ["sqs:SendMessage"],
      "Resource": "arn:aws:sqs:ap-southeast-1:*:ProcessingQueue"
    },
    {
      "Effect": "Allow",
      "Action": ["logs:CreateLogGroup", "logs:CreateLogStream", "logs:PutLogEvents"],
      "Resource": "arn:aws:logs:*:*:log-group:/aws/lambda/*"
    }
  ]
}

Pengujian Lokal dan Deployment ke Produksi

# Build
sam build

# Jalankan API secara lokal
sam local start-api --port 3001

# Invokasi pengujian tunggal
sam local invoke GetUserFunction --event events/get-user.json

# Jalankan semuanya dengan Claude Code
claude -p "
Jalankan sam build,
periksa hasil dengan sam local invoke GetUserFunction --event events/test-get-user.json.
Jika semua baik, jalankan sam deploy --config-env dev.
"

5 Jebakan Paling Umum

1. Inisialisasi yang mengabaikan cold start

// ❌ Membuat klien di dalam handler setiap kali dipanggil
export const handler = async () => {
  const ddb = new DynamoDBClient({});  // ← diinstansiasi setiap invokasi
};

// ✅ Inisialisasi sekali di lingkup modul
const ddb = DynamoDBDocumentClient.from(new DynamoDBClient({}));
export const handler = async () => { /* gunakan ulang ddb */ };

2. Membiarkan timeout pada nilai default (3 detik) Untuk DynamoDB + API eksternal, atur minimal 10-30 detik. Selalu konfigurasi sesuai kebutuhan pemrosesan aktual.

3. Menulis rahasia langsung di variabel lingkungan

# ❌ Hard-coded di template
Environment:
  Variables:
    DB_PASSWORD: "my-secret"

# ✅ Melalui Secrets Manager
Environment:
  Variables:
    DB_PASSWORD: !Sub "{{resolve:secretsmanager:myapp/db-password}}"

4. Keterlambatan cold start dengan Lambda di VPC Menempatkan Lambda di dalam VPC untuk konektivitas RDS menambah beberapa detik pada cold start. Atasi dengan Provisioned Concurrency atau RDS Proxy.

5. Paket deployment yang terlalu besar Mengemas node_modules bersama dapat mencapai batas 250 MB. Pindahkan library bersama ke Lambda Layer.

Ringkasan

TugasKontribusi Claude Code
Implementasi handlerHasilkan definisi tipe, penanganan error, dan logika sekaligus
Template SAMOutput otomatis event, IAM, dan variabel lingkungan
Kebijakan IAMHasilkan desain hak istimewa minimum dengan akurat
Pengujian lokalOtomatiskan eksekusi sam invoke dan evaluasi hasil
DeploymentJalankan build + deploy sebagai alur kerja terpadu

Claude Code mengambil alih bagian paling memakan waktu dalam pengembangan Lambda — definisi tipe dan penulisan template. Fokus pada logika bisnis dapat meningkatkan kecepatan implementasi 3-5 kali lipat.

Artikel Terkait

Kapan Lambda cocok dan kapan tidak

Lambda cocok untuk pekerjaan singkat, berbentuk event, dan aman di-retry: API order, proses gambar setelah upload S3, laporan harian EventBridge, serta webhook Stripe/GitHub. Kurang cocok untuk worker panjang, koneksi persisten, model besar yang harus warm, atau WebSocket stateful kompleks. Minta Claude Code menulis alasan cocok dan tidak cocok dulu.

Istilah dengan bahasa sederhana

TermPlain meaning
handlerThe function Lambda calls. API Gateway passes an HTTP event; S3 passes an object event.
eventThe JSON payload given to Lambda. API Gateway, S3, and EventBridge shapes are different.
least privilegeGrant only the exact actions and resources the function needs.
cold startThe slower first run when Lambda creates a new execution environment.
idempotencyThe same event can run twice without duplicate payment, email, or database writes.

Unit test copy-paste untuk Node.js 24

// test/getUser.test.ts
import { describe, expect, it, vi } from "vitest";
import type { APIGatewayProxyEvent } from "aws-lambda";

const mockSend = vi.fn();
vi.mock("@aws-sdk/lib-dynamodb", async () => {
  const actual = await vi.importActual<typeof import("@aws-sdk/lib-dynamodb")>("@aws-sdk/lib-dynamodb");
  return { ...actual, DynamoDBDocumentClient: { from: () => ({ send: mockSend }) } };
});

const { handler } = await import("../src/functions/getUser/index");

function event(userId?: string): APIGatewayProxyEvent {
  return {
    pathParameters: userId ? { userId } : null,
    httpMethod: "GET",
    path: userId ? "/users/" + userId : "/users",
    headers: {},
    multiValueHeaders: {},
    queryStringParameters: null,
    multiValueQueryStringParameters: null,
    body: null,
    isBase64Encoded: false,
    requestContext: {} as APIGatewayProxyEvent["requestContext"],
    resource: "/users/{userId}",
    stageVariables: null,
  };
}

describe("getUser Lambda", () => {
  it("returns 200 when the user exists", async () => {
    process.env.USERS_TABLE = "UsersTable";
    mockSend.mockResolvedValueOnce({ Item: { userId: "u-1", name: "Masa" } });

    const res = await handler(event("u-1"), {} as never, vi.fn());

    expect(res.statusCode).toBe(200);
    expect(JSON.parse(res.body).userId).toBe("u-1");
  });

  it("returns 400 when path parameter is missing", async () => {
    const res = await handler(event(), {} as never, vi.fn());
    expect(res.statusCode).toBe(400);
  });
});

Pisahkan event API Gateway, S3, dan EventBridge

API Gateway membutuhkanstatusCode danbody. S3 membaca bucket/key dariRecords. EventBridge biasanya memakaisource, detail-type, dan detail. Sebut trigger jelas: HTTP API v2, S3 ObjectCreated, atau EventBridge schedule.

Environment variable, Secrets Manager, dan IAM least privilege

Environment variable untuk config sepertiUSERS_TABLE danAPP_STAGE. API key, password, dan webhook secret masuk Secrets Manager; Lambda hanya menerima ARN. IAM harus memakai action dan ARN spesifik.

CloudWatch Logs, retry, dan idempotency

CloudWatch Logs adalah tempat diagnosis pertama. Jika logs kosong, cek region, nama fungsi, permission role, dan stack. S3, EventBridge, dan async invoke bisa retry; gunakan ID sebagai idempotency key.

Prompt review keamanan untuk Claude Code

Review this AWS Lambda change before production.
Check handler shape, API Gateway/S3/EventBridge event type, IAM least privilege, Secrets Manager usage, CloudWatch Logs, retries, idempotency, cold starts, timeout, memory, and cost risk.
Return blockers first, then recommended fixes, missing tests, and human approvals required before deploy.

CTA monetisasi, training, dan konsultasi

ClaudeCodeLab menyediakan training dan konsultasi untuk Lambda, IAM, SAM, audit log, dan review gate. Individu mulai dari PDF gratis dan Gumroad; tim memakai training dan konsultasi untuk permission, approval, dan revenue path.

Hasil praktik

Contoh dipisah menjadi handler dan test yang bisa dicek dengannpm test. Saya tidak menjalankansam deploy real karena account, region, ARN, dan tabel berbeda. Produksi perlu catatansam validate --lint, sam build, sam local invoke, logs, dan IAM diff.

Referensi

#claude-code #aws #lambda #serverless #api-gateway #typescript
Gratis

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.

Masa

Tentang penulis

Masa

Engineer yang berfokus pada workflow Claude Code praktis dan adopsi tim.