Configuration
For the complete documentation index, see llms.txt. Prefer markdown by appending .md to documentation URLs or sending Accept: text/markdown.

Wrangler and bindings

Configure Cloudflare bindings in wrangler.jsonc. D1, KV, R2, Queues, Email, AI, rate limits, flags, routes, and generated types.

wrangler.jsonc is the source of truth for your Cloudflare infrastructure. It declares the Worker, its routes, non-secret variables, and every binding. The Cloudflare Vite plugin reads it in development, and wrangler deploy reads it in production.

Update the relevant fields in your existing file. Keep its compatibility_date and compatibility_flags, change them deliberately when adopting and testing new Workers runtime behavior.

wrangler.jsonc
{
  "name": "edge",
  // Keep your project's compatibility_date.
  "compatibility_flags": ["nodejs_compat"],
  "main": "src/server.ts",
  "vars": {
    "BETTER_AUTH_URL": "https://edge.turbostarter.dev",
    "EMAIL_FROM": "TurboEdge <noreply@edge.turbostarter.dev>",
    "VITE_PRODUCT_NAME": "TurboEdge",
    "VITE_URL": "https://edge.turbostarter.dev"
  },
  ...
}

Production resources

The committed file points at the demo's resources. Before you deploy, swap the name, domain, vars, and every binding ID for your own resources.

Bindings

BindingTypeUsed for
DBD1Application database (Drizzle)
KVKV namespaceCaching and app configuration
UPLOADSR2 bucketFile storage and delivery
QUEUEQueue producerBackground job delivery
EMAILSend emailTransactional email
AUTH_RATE_LIMITRate limitThrottling sign-in routes
FLAGSFlagshipFeature flags (remote in dev)
AIWorkers AIAI inference (remote in dev)

Use them anywhere on the server through the runtime:

import { env } from "cloudflare:workers";

const user = await env.DB.prepare("SELECT 1").first();

D1

wrangler.jsonc
"d1_databases": [
  {
    "binding": "DB",
    "database_name": "edge-production",
    "database_id": "<your-database-id>",
    "migrations_dir": "drizzle"
  }
]

Create your database with pnpm wrangler d1 create <name> and paste the returned database_id. migrations_dir points Wrangler at the Drizzle output.

KV

wrangler.jsonc
"kv_namespaces": [{ "binding": "KV", "id": "<your-namespace-id>" }]

The KV binding and src/lib/kv.ts helper are already wired. Use them for cached public content, read-heavy lookup data, or application settings such as homepage announcements. The helper exposes kv.get, kv.put, and kv.remove.

Create your production namespace with pnpm wrangler kv namespace create KV and put its ID in wrangler.jsonc. Local development provides a local namespace that you can inspect in Local Explorer.

For example, add server-side helpers for a homepage announcement:

import { env } from "cloudflare:workers";

import { kv } from "@/lib/kv";

export const setAnnouncement = (value: string) =>
  kv.put({
    namespace: env.KV,
    key: "homepage:announcement",
    value,
    options: { expirationTtl: 3600 },
  });

export const getAnnouncement = () =>
  kv.get({
    namespace: env.KV,
    key: "homepage:announcement",
  });

kv.get returns the stored string or null. When you withdraw an announcement, call kv.remove({ namespace: env.KV, key: "homepage:announcement" }). Keep writes behind an authorized server function, and return the value to your UI through a server function.

KV is optimized for frequent reads with infrequent updates. Use it for data that tolerates a short update delay; keep transactions and permission checks in D1.

The caching guide covers key design, expiration, invalidation, and the relationship between KV and client query caches.

R2

wrangler.jsonc
"r2_buckets": [{ "binding": "UPLOADS", "bucket_name": "<your-bucket>" }]

Create it with pnpm wrangler r2 bucket create <name>.

Queues

wrangler.jsonc
"queues": {
  "producers": [{ "binding": "QUEUE", "queue": "<your-queue>" }],
  "consumers": [{ "queue": "<your-queue>" }]
}

The same Worker produces and consumes jobs. Job handlers live in src/lib/queue/jobs. Create the queue with pnpm wrangler queues create <name>.

Email

wrangler.jsonc
"send_email": [
  {
    "name": "EMAIL",
    "allowed_sender_addresses": ["noreply@<your-domain>"]
  }
]

EMAIL_FROM must use an address listed in allowed_sender_addresses, on a domain you've onboarded to Cloudflare Email.

Rate limit

wrangler.jsonc
"ratelimits": [
  {
    "name": "AUTH_RATE_LIMIT",
    "namespace_id": "91001",
    "simple": { "limit": 10, "period": 60 }
  }
]

Allows 10 requests per 60 seconds on the auth routes. Pick a unique namespace_id per account and tune limit and period as needed.

Feature flags and AI

wrangler.jsonc
"flagship": [{ "binding": "FLAGS", "app_id": "<your-app-id>", "remote": true }],
"ai": { "binding": "AI", "remote": true }

These are remote bindings: Wrangler can't simulate them, even with "remote": false. Local dev needs CLOUDFLARE_API_TOKEN or pnpm wrangler login and valid resources in your account. A remote proxy error can prevent startup. The flags helper returns a default for evaluation failures after startup; it does not repair remote credentials or an invalid app ID.

Follow feature flags for typed values, targeting, and rollouts, and AI setup for gateway and model access.

Routes and domain

wrangler.jsonc
"routes": [{ "pattern": "<your-domain>", "custom_domain": true }]

With custom_domain, Cloudflare creates the DNS record and certificate for you. Remove the block to use only the workers.dev URL ("workers_dev": true).

Observability

Logs and traces are on by default through the observability block, with full sampling. Lower head_sampling_rate if volume or cost becomes a concern. Use log from src/lib/log.ts for structured logs.

See observability for request IDs, production logs, analytics, and liveness checks.

Binding types

Binding types live in worker-configuration.d.ts, generated from this file. After any change, run:

pnpm cf-typegen

Never edit the generated file by hand.

How is this guide?

Last updated on

On this page

Ship globally on the edge. In minutes.Try Edge Kit