Przejdź do głównej zawartości

Wzorce rozwoju serverless

Wzorce rozwoju serverless dla asystentów AI eliminują luki niezawodności, które Cursor, Claude Code i Codex zostawiają w AWS Lambda, Cloudflare Workers i Vercel: idempotentne handlery deduplikujące ponowione zdarzenia S3, SQS i EventBridge, strukturalne logowanie do CloudWatch, API gateway na Cloudflare Workers z pasującym wrangler.toml, podgląd żywej infrastruktury przez serwer MCP Cloudflare oraz triage cold startów przed opłaceniem provisioned concurrency.

Twoja Lambda przetwarzająca obrazy odpala się dwa razy na ten sam upload do S3, więc połowa miniatur zostaje zapisana, usunięta i zapisana ponownie — a CloudWatch to ściana nieustrukturyzowanych console.log, których nie da się powiązać z żadnym żądaniem. W międzyczasie p99 skacze co rano do 4 sekund przez cold starty, a „poprawka”, którą ktoś wdrożył (provisioned concurrency na każdej funkcji), podwoiła rachunek. Serverless usuwa serwery, a nie problemy systemów rozproszonych: ponowienia, idempotencja, cold starty i limity poszczególnych platform to teraz Twój kod.

Ten przepis pokazuje, jak sterować Cursor, Claude Code i Codex, by generowały kod serverless, który przetrwa te problemy — a nie demo na szczęśliwej ścieżce, które psuje się przy pierwszym ponownym dostarczeniu wiadomości przez SQS.

  • Gotowy prompt, który tworzy idempotentny handler AWS Lambda (deduplikacja przy ponowieniach) ze strukturalnym logowaniem do CloudWatch
  • Wzorzec API gateway na Cloudflare Workers z prawdziwym wrangler.toml oraz to, jak serwer MCP Cloudflare podgląda KV/R2/D1 bez wychodzenia z edytora
  • Workflow triage cold startów, który mówi, kiedy provisioned concurrency naprawdę jest warta swojej ceny
  • Podział na trzy narzędzia: kiedy używać agenta w Cursor, headless runs w Claude Code i Codex Cloud do PR-ów wdrożeniowych
  • Tryby awarii, które gryzą na produkcji — zduplikowane dostarczenia z SQS, hot partitions w DynamoDB, limity CPU w Workers — oraz prompty, które im zapobiegają

Krok 1: Zbuduj szkielet usługi (gdzie trzy narzędzia się różnią)

Dział zatytułowany „Krok 1: Zbuduj szkielet usługi (gdzie trzy narzędzia się różnią)”

Etap budowania szkieletu to moment, w którym ergonomia narzędzi rozjeżdża się najbardziej. Cursor edytuje pliki wizualnie w Twoim repozytorium; Claude Code uruchamia CLI frameworka z terminala i da się skryptować w CI; Codex potrafi rozdzielić to samo zadanie do worktree w chmurze i otworzyć PR wdrożeniowy. Wybieraj według tego, gdzie żyje praca, a nie według możliwości — wszystkie trzy sterują tymi samymi CLI: AWS SAM / Serverless Framework / Wrangler.

Otwórz tryb Agent (Cmd/Ctrl + I) w pustym repozytorium i daj mu jedną konkretną usługę do zbudowania:

Set up a Serverless Framework v4 service in TypeScript targeting AWS eu-central-1. One HTTP Lambda behind API Gateway (GET /health), one S3-triggered Lambda for image processing, and a DynamoDB table media (PK id). Use esbuild bundling, Node 22 runtime, and put stage/region in serverless.yml provider vars. Add a dev and prod stage.

Agent pisze serverless.yml, zaślepki handlerów i package.json. Przejrzyj diff w pasku bocznym przed zaakceptowaniem — Cursor zapisuje checkpoint przy każdej edycji, więc możesz cofnąć zły plik bez utraty reszty.

Krok 2: Uczyń handler idempotentnym (część, którą dema pomijają)

Dział zatytułowany „Krok 2: Uczyń handler idempotentnym (część, którą dema pomijają)”

S3, SQS i EventBridge dostarczają co najmniej raz. Naiwny handler przetwarza ten sam obiekt ponownie przy retry. Rozwiązaniem jest klucz deduplikacji — dla S3 to eTag obiektu — sprawdzany zapisem warunkowym przed wykonaniem pracy. To najcenniejsza rzecz, jaką możesz umieścić w prompcie, więc powiedz to wprost:

Ten prompt tworzy coś zbliżonego do tego — zwróć uwagę na wczesny return przy duplikacie i strukturalny log, bo to właśnie czyni kod możliwym do debugowania na produkcji:

// handler.ts — the AI-generated shape worth reviewing for
import { S3Event } from 'aws-lambda';
import { DynamoDBClient, PutItemCommand } from '@aws-sdk/client-dynamodb';
const ddb = new DynamoDBClient({});
export const handler = async (event: S3Event) => {
const start = Date.now();
for (const rec of event.Records) {
const { bucket, object } = rec.s3;
const pk = `${bucket.name}/${object.key}#${object.eTag}`;
const log = { requestId: rec.responseElements['x-amz-request-id'], bucket: bucket.name, key: object.key, eTag: object.eTag };
try {
await ddb.send(new PutItemCommand({
TableName: process.env.DEDUPE_TABLE!,
Item: { pk: { S: pk } },
ConditionExpression: 'attribute_not_exists(pk)',
}));
} catch (err: any) {
if (err.name === 'ConditionalCheckFailedException') {
console.log(JSON.stringify({ ...log, status: 'duplicate-skipped' }));
continue; // already processed — S3 redelivery
}
throw err;
}
// ... resize with sharp, write derived/ objects ...
console.log(JSON.stringify({ ...log, status: 'ok', durationMs: Date.now() - start }));
}
};

To, co trzeba zweryfikować w wyniku AI: że zapis deduplikacyjny dzieje się przed efektami ubocznymi oraz że blok catch ponownie rzuca wyjątek (żeby DLQ faktycznie łapał awarie), zamiast go połykać.

Na Workers ograniczenia są inne — brak środowiska Node, budżet czasu CPU na żądanie i bindings zamiast klientów SDK. Poproś o gateway i konfigurację razem, żeby bindings w wrangler.toml pasowały do kodu:

# wrangler.toml — the AI should produce bindings that match the Worker
name = "api-gateway"
main = "src/index.ts"
compatibility_date = "2026-06-01"
[vars]
ORIGIN = "https://origin.internal.example.com"
[[kv_namespaces]]
binding = "TOKENS"
id = "<your-kv-id>"
[[durable_objects.bindings]]
name = "RATE_LIMITER"
class_name = "RateLimiter"
[[migrations]]
tag = "v1"
new_sqlite_classes = ["RateLimiter"]

Krok 4: Podgląd działającej infrastruktury serwerem MCP Cloudflare

Dział zatytułowany „Krok 4: Podgląd działającej infrastruktury serwerem MCP Cloudflare”

Wygenerowanie Workera to połowa roboty; błędy żyją w wartościach bindings — źle wpisane id namespace’u KV, nieaktualny wiersz w D1. Bez MCP przełączasz się alt-tabem między dashboardem a edytorem. Z zarządzanymi zdalnymi serwerami MCP Cloudflare AI czyta rzeczywisty stan Twojego konta oraz dokumentację w tej samej rozmowie. Konfiguracja jest identyczna we wszystkich trzech narzędziach — wskaż im zdalne endpointy (pełny katalog serwerów i przepływ OAuth w przewodniku Cloudflare MCP):

{
"mcpServers": {
"cloudflare-bindings": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://bindings.mcp.cloudflare.com/mcp"]
},
"cloudflare-observability": {
"command": "npx",
"args": ["-y", "mcp-remote", "https://observability.mcp.cloudflare.com/mcp"]
}
}
}

Przed MCP debugowanie błędu nieaktualnego cache oznaczało kopiowanie id namespace’ów między czterema kartami przeglądarki. Po: „Read the TOKENS KV namespace bound to the api-gateway Worker and list the keys written in the last hour” i AI odpowiada na podstawie Twojego działającego konta. Do wdrożeń i edycji bindings z CLI lżejszą alternatywą jest skill Cloudflare wrangler — zainstaluj go poleceniem npx skills add cloudflare/skills/wrangler (z repozytorium cloudflare/skills, wymienionego na skills.sh). Skill lepiej pasuje, gdy chcesz tylko, by agent znał polecenia i konwencje wrangler; serwer MCP wygrywa, gdy potrzebujesz, by czytał stan na żywo.