Use Cases (Atualizado: 01/06/2026)

Serverless Functions com Claude Code: Lambda e Workers

Guia pratico para criar serverless functions com Claude Code: prompt, plataforma, env/secrets, idempotencia, retries, testes e deploy.

Serverless Functions com Claude Code: Lambda e Workers

Serverless functions sao pequenos trechos de codigo executados a cada evento ou requisicao HTTP, sem manter um servidor sempre ligado. Elas combinam bem com webhooks, APIs pequenas, entradas para processamento de imagens ou CSV, e regras na borda. Mesmo assim, timeout, retry, secrets, permissoes, logs e custos continuam sendo decisoes de producao.

Claude Code ajuda porque consegue manter handler, fixture de evento, testes, notas de deploy e checklist de revisao no mesmo contexto. O fluxo seguro nao e deixar a IA publicar sozinha. O fluxo seguro e: escrever requisitos, escolher runtime e plataforma, reproduzir o evento localmente, separar configuracao e secrets, desenhar idempotencia, testar falhas e pedir revisao humana para exposicao e custo.

Use a documentacao oficial como base: AWS Lambda Documentation, Lambda com Node.js, Cloudflare Workers development and testing e Workers get started guide. Para aprofundar, veja o guia AWS Lambda, o guia Cloudflare Workers, o guia de desenvolvimento de APIs e o guia de gerenciamento de secrets.

Comece Pelo Caso De Uso

Serverless funciona melhor quando o trabalho e curto, orientado a evento e pode ser repetido sem corromper dados.

Caso de usoPor que encaixaClaude Code pode rascunharRevisao humana
Webhook de pagamento ou formularioUma requisicao vira um eventoVerificacao de assinatura, fixture, errosSecrets, duplicados, replay
Entrada de resize ou CSVTrabalho pesado vai para storage ou filaValidacao, job ID, logs JSONTamanho de arquivo, timeout, cleanup
API JSON internaPequenos endpoints sem servidor persistenteHandler, testes, routeAuth, CORS, exposicao, rate limit
Redirect/cache na bordaResposta perto do usuarioWorker route, cache headers, rolloutPurge de cache, dados pessoais, SEO
flowchart LR
  A[Prompt de requisitos] --> B[Escolher Lambda ou Workers]
  B --> C[Reproduzir evento local]
  C --> D[Separar env e secrets]
  D --> E[Idempotencia e retry]
  E --> F[Testes]
  F --> G[Deploy em dev]
  G --> H[Logs e cleanup]

Prompt Para Claude Code

Crie uma serverless function minima em Node.js.

Objetivo:
- Processar POST /orders e retornar uma resposta accepted
- Rodar localmente com node local-test.mjs
- Assumir eventos AWS Lambda HTTP API v2

Requisitos:
- Explicar index.mjs, events/create-order.json, local-test.mjs e index.test.mjs
- Retornar 400 quando idempotency-key faltar
- Retornar a mesma resposta quando idempotency-key repetir
- Separar invalid JSON, invalid input e unsupported route
- Logs em JSON sem secrets nem dados pessoais
- Incluir checklist pre-deploy

Restricoes:
- Sem pacotes npm externos
- Em producao, idempotencia deve usar DynamoDB, KV ou outro storage duravel
- IAM, URLs publicas e recursos pagos exigem confirmacao humana

Lambda Ou Workers

AWS Lambda e natural quando voce usa eventos AWS, IAM, S3, DynamoDB, SQS ou EventBridge. Cloudflare Workers e melhor quando o trabalho central e HTTP na borda: redirects, APIs leves, cache, validacao simples, KV/D1/R2. Vercel Functions ajuda em apps Next.js, mas aqui os exemplos ficam em Lambda e Workers.

CriterioAWS LambdaCloudflare Workers
Melhor paraIntegracoes AWS, APIs de negocio, jobs asyncHTTP edge, routing, cache, APIs leves
LocalNode.js, SAM, AWS CLIWrangler
PermissoesIAM role e policyBindings, secrets, permissoes da conta
Risco comumIAM amplo, custo VPC/NAT, logs demaisDrift de bindings, limites runtime, KV consistency

Handler Lambda Executavel

// index.mjs
import crypto from "node:crypto";

const localIdempotencyStore = new Map();

function json(statusCode, body) {
  return {
    statusCode,
    headers: { "content-type": "application/json" },
    body: JSON.stringify(body),
  };
}

function readHeader(headers = {}, name) {
  const target = name.toLowerCase();
  const found = Object.entries(headers).find(([key]) => key.toLowerCase() === target);
  return found?.[1];
}

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 method = event.requestContext?.http?.method ?? event.httpMethod ?? "GET";
  const path = event.rawPath ?? event.path ?? "/";
  const requestId = context.awsRequestId ?? crypto.randomUUID();

  console.log(JSON.stringify({ level: "info", message: "request.start", requestId, method, path }));

  if (method !== "POST" || path !== "/orders") {
    return json(404, { error: "not_found" });
  }

  const idempotencyKey = readHeader(event.headers, "idempotency-key");
  if (!idempotencyKey) {
    return json(400, { error: "idempotency_key_required" });
  }

  if (localIdempotencyStore.has(idempotencyKey)) {
    return json(200, { ...localIdempotencyStore.get(idempotencyKey), replay: true });
  }

  let body;
  try {
    body = parseBody(event);
  } catch {
    return json(400, { error: "invalid_json" });
  }

  if (!Number.isFinite(body.amount) || body.amount <= 0 || typeof body.currency !== "string") {
    return json(400, { error: "invalid_order" });
  }

  const accepted = {
    orderId: crypto.randomUUID(),
    status: "accepted",
    amount: body.amount,
    currency: body.currency,
  };

  localIdempotencyStore.set(idempotencyKey, accepted);
  console.log(JSON.stringify({ level: "info", message: "order.accepted", requestId, orderId: accepted.orderId }));

  return json(202, accepted);
}
{
  "version": "2.0",
  "routeKey": "POST /orders",
  "rawPath": "/orders",
  "headers": {
    "content-type": "application/json",
    "idempotency-key": "demo-key-001"
  },
  "requestContext": {
    "http": {
      "method": "POST",
      "path": "/orders"
    }
  },
  "body": "{\"amount\":3200,\"currency\":\"BRL\"}",
  "isBase64Encoded": false
}
// local-test.mjs
import { readFile } from "node:fs/promises";
import { handler } from "./index.mjs";

const eventPath = process.argv[2] ?? "events/create-order.json";
const event = JSON.parse(await readFile(eventPath, "utf8"));

const first = await handler(event, { awsRequestId: "local-001" });
const second = await handler(event, { awsRequestId: "local-002" });

console.log("first:", first.statusCode, first.body);
console.log("second:", second.statusCode, second.body);
node local-test.mjs events/create-order.json

A Map e apenas demo local. Em producao, use escrita condicional no DynamoDB, unique constraint no banco, Cloudflare KV/D1 ou outro storage duravel.

Testes

// index.test.mjs
import crypto from "node:crypto";
import test from "node:test";
import assert from "node:assert/strict";
import { handler } from "./index.mjs";

function event(overrides = {}) {
  return {
    rawPath: "/orders",
    headers: { "idempotency-key": crypto.randomUUID() },
    requestContext: { http: { method: "POST" } },
    body: JSON.stringify({ amount: 1200, currency: "BRL" }),
    isBase64Encoded: false,
    ...overrides,
  };
}

test("requires idempotency-key", async () => {
  const result = await handler(event({ headers: {} }), {});
  assert.equal(result.statusCode, 400);
});

test("accepts a valid order", async () => {
  const result = await handler(event(), {});
  assert.equal(result.statusCode, 202);
  assert.equal(JSON.parse(result.body).status, "accepted");
});

test("rejects invalid JSON", async () => {
  const result = await handler(event({ body: "not-json" }), {});
  assert.equal(result.statusCode, 400);
});
node --test index.test.mjs

Versao Workers Com KV

// src/worker.js
export default {
  async fetch(request, env) {
    const url = new URL(request.url);

    if (request.method !== "POST" || url.pathname !== "/orders") {
      return Response.json({ error: "not_found" }, { status: 404 });
    }

    if (request.headers.get("x-webhook-secret") !== env.WEBHOOK_SECRET) {
      return Response.json({ error: "unauthorized" }, { status: 401 });
    }

    const idempotencyKey = request.headers.get("idempotency-key");
    if (!idempotencyKey) {
      return Response.json({ error: "idempotency_key_required" }, { status: 400 });
    }

    const existing = await env.IDEMPOTENCY_KV.get(idempotencyKey, "json");
    if (existing) {
      return Response.json({ ...existing, replay: true });
    }

    const body = await request.json();
    if (!Number.isFinite(body.amount) || typeof body.currency !== "string") {
      return Response.json({ error: "invalid_order" }, { status: 400 });
    }

    const accepted = {
      orderId: crypto.randomUUID(),
      status: "accepted",
      amount: body.amount,
      currency: body.currency,
    };

    await env.IDEMPOTENCY_KV.put(idempotencyKey, JSON.stringify(accepted), {
      expirationTtl: 86400,
    });

    return Response.json(accepted, { status: 202 });
  },
};
npm create cloudflare@latest serverless-orders-worker
cd serverless-orders-worker
npx wrangler kv namespace create IDEMPOTENCY_KV
npx wrangler secret put WEBHOOK_SECRET
npx wrangler dev

Armadilhas E Checklist

A primeira armadilha e assumir execucao exatamente uma vez. Webhooks, filas, eventos async e navegadores podem repetir. A segunda e vazar secrets em logs ou exemplos. A terceira e aceitar permissao ampla como Resource: "*". A quarta e publicar uma URL sem dono, auth, CORS, rate limit, retencao de logs e plano de limpeza.

CheckConfirmar
RequisitosInput, output, owner e erros documentados
RuntimeLambda Node.js runtime ou Workers compatibility_date explicito
LocalFixture e node --test passam
Env/secretsConfig e secrets separados
IdempotenciaRetry nao duplica cobranca ou cadastro
Timeout/retryTrabalho lento vai para fila ou job duravel
ObservabilidadeLogs JSON, error rate, alertas e retention definidos
CleanupComandos de exclusao ou passos no dashboard escritos
zip function.zip index.mjs
aws lambda update-function-code \
  --function-name serverless-orders-dev \
  --zip-file fileb://function.zip

npx wrangler deploy

Prompt final:

Revise esta serverless function antes de publicar.
Separe blocking issues, non-blocking improvements e human confirmations.
Verifique idempotencia, timeout/retry, secrets, IAM ou bindings, logs,
reproducibilidade local, cleanup, links oficiais e links internos.

ClaudeCodeLab organiza esses padroes em produtos e templates de Claude Code. Para desenhar permissoes AWS, CLAUDE.md, prompts de revisao e aprovacao de deploy em um repositorio real, veja a pagina de consultoria e treinamento Claude Code.

No teste pratico, o maior ganho veio de criar o fixture de evento primeiro. Claude Code e rapido, mas retries, secrets e cleanup so ficam confiaveis quando essas restricoes aparecem no primeiro prompt.

#Claude Code #serverless functions #AWS Lambda #Cloudflare Workers #Vercel
Grátis

PDF grátis: cheatsheet do Claude Code

Informe seu e-mail e baixe uma página com comandos, hábitos de revisão e workflows seguros.

Cuidamos dos seus dados e não enviamos spam.

Masa

Sobre o autor

Masa

Engenheiro focado em workflows práticos com Claude Code.