Claude Code से Cloudflare Workers API बनाना
Claude Code के साथ Workers API, Wrangler, KV/D1/R2, cache, rate limit, logs और security headers लागू करें।
Cloudflare Workers JavaScript और TypeScript को Cloudflare के edge network पर चलाता है। Edge का सरल मतलब है: code user के पास वाली जगह पर execute होता है, सिर्फ एक central region में नहीं। यह छोटे API, webhook, BFF, cached response, security check और R2 से controlled download के लिए अच्छा विकल्प है।
Claude Code यहां उपयोगी है क्योंकि Worker project साफ हिस्सों में बंटता है: fetch handler, wrangler.toml, और KV/D1/R2 जैसे bindings। 3 जून 2026 को official docs फिर से जांचे गए; काम शुरू करने से पहले Workers, Wrangler, bindings, KV, D1, R2, Cache API, Rate Limiting और Workers Logs खोलें। तुलना के लिए serverless functions और AWS Lambda guide भी देखें।
हम क्या बनाएंगे
यह example orders API है। D1 orders रखेगा, KV small settings रखेगा, R2 receipt JSON रखेगा, Cache API safe GET response को थोड़े समय के लिए cache करेगा, Rate Limiting abuse रोकेगा, Workers Logs structured logs रखेगा, और हर response में security headers होंगे।
flowchart LR
Client["Client"] --> Worker["Worker fetch handler"]
Worker --> D1["D1 orders"]
Worker --> KV["KV settings"]
Worker --> R2["R2 receipts"]
Worker --> Cache["Cache API"]
Worker --> Logs["Workers Logs"]
Binding को आसान भाषा में Worker को दी गई external capability समझें। binding = "DB" लिखने पर code में वही resource env.DB बन जाता है।
Claude Code prompt
Cloudflare Workers + TypeScript से orders API implement करें।
Files:
- src/index.ts
- wrangler.toml
- schema.sql
Requirements:
- module fetch handler format इस्तेमाल करें
- GET /health JSON लौटाए
- GET /orders/:id D1 से एक row पढ़े और सिर्फ safe public output को 30 seconds cache करे
- POST /orders JSON validate करके D1 में insert करे
- Authorization Bearer token को API_TOKEN से check करे
- SETTINGS KV, DB D1, RECEIPTS R2, API_RATE_LIMITER bindings इस्तेमाल करे
- हर response में security headers जोड़ें
- console.log JSON object के रूप में लिखें
- curl verification commands दें
Do not:
- secret values को wrangler.toml में न लिखें
- long-running Node.js server assume न करें
- pseudocode न दें
Wrangler setup
npm create cloudflare@latest claude-worker-api -- --type=hello-world
cd claude-worker-api
npm install -D typescript wrangler
npx wrangler --version
C3 नए projects में wrangler.jsonc बना सकता है। Wrangler JSON/JSONC और TOML config files support करता है; यह article readability के लिए TOML दिखाता है। अगर आपके project में wrangler.jsonc है, तो वही keys JSONC में रखें।
name = "claude-worker-api"
main = "src/index.ts"
compatibility_date = "2026-06-03"
[vars]
PUBLIC_ENV = "production"
[observability]
enabled = true
head_sampling_rate = 1
[[d1_databases]]
binding = "DB"
database_name = "claude-worker-api"
database_id = "replace-with-d1-database-id"
[[kv_namespaces]]
binding = "SETTINGS"
id = "replace-with-kv-namespace-id"
[[r2_buckets]]
binding = "RECEIPTS"
bucket_name = "claude-worker-receipts"
[[ratelimits]]
name = "API_RATE_LIMITER"
namespace_id = "1001"
[ratelimits.simple]
limit = 60
period = 60
npx wrangler login
npx wrangler d1 create claude-worker-api
npx wrangler kv namespace create SETTINGS
npx wrangler r2 bucket create claude-worker-receipts
npx wrangler secret put API_TOKEN
D1 schema
CREATE TABLE IF NOT EXISTS orders (
id TEXT PRIMARY KEY,
email TEXT NOT NULL,
amount INTEGER NOT NULL,
status TEXT NOT NULL DEFAULT 'pending',
created_at TEXT NOT NULL DEFAULT CURRENT_TIMESTAMP
);
CREATE INDEX IF NOT EXISTS idx_orders_email ON orders(email);
npx wrangler d1 execute claude-worker-api --local --file=./schema.sql
npx wrangler d1 execute claude-worker-api --remote --file=./schema.sql
Runnable Worker
export interface Env {
API_TOKEN: string;
PUBLIC_ENV: string;
DB: D1Database;
SETTINGS: KVNamespace;
RECEIPTS: R2Bucket;
API_RATE_LIMITER: RateLimit;
}
const securityHeaders = {
"content-security-policy": "default-src 'none'; frame-ancestors 'none'",
"x-content-type-options": "nosniff",
"x-frame-options": "DENY",
"referrer-policy": "no-referrer",
"permissions-policy": "camera=(), microphone=(), geolocation=()",
};
function json(data: unknown, init: ResponseInit = {}) {
return new Response(JSON.stringify(data), {
...init,
headers: {
"content-type": "application/json; charset=utf-8",
...securityHeaders,
...init.headers,
},
});
}
export default {
async fetch(request, env, ctx): Promise<Response> {
const url = new URL(request.url);
const requestId = crypto.randomUUID();
console.log({ event: "request_started", requestId, method: request.method, path: url.pathname });
if (url.pathname === "/health") {
const maintenance = await env.SETTINGS.get("maintenance");
return json({ ok: true, env: env.PUBLIC_ENV, maintenance: maintenance === "true" });
}
if (request.headers.get("authorization") !== `Bearer ${env.API_TOKEN}`) {
return json({ error: "unauthorized" }, { status: 401 });
}
const { success } = await env.API_RATE_LIMITER.limit({
key: request.headers.get("authorization")?.slice(-16) ?? "anonymous",
});
if (!success) return json({ error: "rate_limited" }, { status: 429 });
const match = url.pathname.match(/^\/orders\/([a-zA-Z0-9_-]+)$/);
if (request.method === "GET" && match) {
const cacheKey = new Request(url.toString(), { method: "GET" });
const cached = await caches.default.match(cacheKey);
if (cached) return cached;
const order = await env.DB.prepare(
"SELECT id, email, amount, status, created_at FROM orders WHERE id = ?"
).bind(match[1]).first();
if (!order) return json({ error: "not_found" }, { status: 404 });
const response = json({ order }, {
headers: { "cache-control": "public, max-age=30", "cache-tag": `order-${match[1]}` },
});
ctx.waitUntil(caches.default.put(cacheKey, response.clone()));
return response;
}
if (request.method === "POST" && url.pathname === "/orders") {
const body = await request.json<{ email?: string; amount?: number }>();
if (!body.email?.includes("@") || !Number.isInteger(body.amount) || body.amount <= 0) {
return json({ error: "invalid_order" }, { status: 400 });
}
const id = crypto.randomUUID();
await env.DB.prepare(
"INSERT INTO orders (id, email, amount, status) VALUES (?, ?, ?, ?)"
).bind(id, body.email, body.amount, "pending").run();
await env.RECEIPTS.put(`orders/${id}.json`, JSON.stringify({ id, email: body.email, amount: body.amount }), {
httpMetadata: { contentType: "application/json" },
});
console.log({ event: "order_created", requestId, orderId: id });
return json({ id, status: "pending" }, { status: 201 });
}
return json({ error: "not_found" }, { status: 404 });
},
} satisfies ExportedHandler<Env>;
Local test और deploy
printf "API_TOKEN=dev-token\n" > .dev.vars
npx wrangler dev
curl http://localhost:8787/health
curl -X POST http://localhost:8787/orders \
-H "authorization: Bearer dev-token" \
-H "content-type: application/json" \
-d "{\"email\":\"masa@example.com\",\"amount\":1200}"
curl http://localhost:8787/orders/replace-with-created-id \
-H "authorization: Bearer dev-token"
npx wrangler secret put API_TOKEN
npx wrangler d1 execute claude-worker-api --remote --file=./schema.sql
npx wrangler deploy
npx wrangler tail
Real use cases
पहला use case form या order API है। D1 status रखता है, R2 receipt या attachment रखता है, और Workers Logs debugging में मदद करते हैं।
दूसरा use case webhook receiver है। Signature verify करें, event ID D1 में रखें और duplicate event को skip करें।
तीसरा use case BFF है, यानी Backend for Frontend। Worker upstream API key छिपाता है, response को UI के हिसाब से बदलता है और सिर्फ safe data cache करता है।
चौथा use case R2 file delivery है। बड़ी file R2 में रहेगी, authorization और logs Worker में रहेंगे।
Pitfalls
Workers को persistent Node.js server की तरह न लिखें। Web APIs, Request, Response, fetch, crypto और bindings पर design करें।
Storage roles न मिलाएं। KV small key-value के लिए, D1 relational data के लिए, R2 objects के लिए और Cache API short-lived response cache के लिए है।
Private response cache न करें। Cookie, token, email या user-specific output shared cache में नहीं जाना चाहिए।
Rate limit सिर्फ IP पर न करें। API key, user ID या tenant ID अधिक भरोसेमंद key है।
कौन सा platform चुनें
Cloudflare cache और bindings के पास low-latency HTTP API चाहिए तो Workers चुनें। Cloudflare Pages site के साथ थोड़ा dynamic logic चाहिए तो Pages Functions चुनें। Container, long task या full framework चाहिए तो Cloud Run चुनें। AWS S3, DynamoDB, EventBridge या SQS केंद्र में हों तो Lambda बेहतर है।
Claude Code review prompt
इस Cloudflare Workers implementation को review करें।
Check करें:
- Workers runtime compatibility
- Env type और wrangler binding names match करते हैं या नहीं
- code, logs या config में secret leak है या नहीं
- D1 bind usage और SQL injection risk
- unsafe Cache API usage
- Rate Limiting key choice
- हर response में security headers
- missing curl verification steps
Output severity order में findings, fixes और tests दें।
CTA और verification note
पहले सिर्फ एक endpoint migrate करें: /health, read-only GET या webhook। Claude Code को exact files, binding names, verification commands और forbidden shortcuts दें। Reusable templates के लिए products देखें; team training और review habits के लिए training देखें।
असल में आजमाने का परिणाम: इस article का flow Wrangler, D1, Worker और curl के रूप में जोड़ा गया है; production से पहले अपने Cloudflare account में wrangler deploy, wrangler tail, headers, cache और 429 behavior फिर से जांचें।
मुफ़्त PDF: Claude Code cheatsheet
Email डालें और commands, review habits तथा safe workflow वाली एक-page PDF पाएँ.
हम आपका data सुरक्षित रखते हैं और spam नहीं भेजते.
लेखक के बारे में
Masa
Claude Code workflow और team adoption पर काम करने वाला engineer.
संबंधित लेख
Claude Code Obsidian to CLAUDE.md workflow: context बार-बार न समझाएं
Obsidian notes को CLAUDE.md operating notes में बदलकर Claude Code sessions को resume करना आसान बनाएं.
Claude Code Revenue CTA Routing: article से PDF, Gumroad और consultation तक
Reader intent के आधार पर free PDF, Gumroad products और consultation तक CTA route करने वाला workflow.
Claude Code टीम हैंडऑफ नियम: review proof, permissions, rollback और revenue path
Claude Code टीम काम के लिए evidence, permission rules, rollback, free PDF, Gumroad और consultation path वाला handoff.