Tools of the Trade

How it works

Every demo here is a real, working proof-of-concept on Cloudflare's actual platform. Not slideware. The whole site runs on Cloudflare Pages + Pages Functions; each bounty below is one primitive doing one job at the edge.

👤 Visitor 🌐 Cloudflare Pages + Functions (the edge) one primitive per bounty:

Scale-to-zero serverless: idle costs nothing. No Workers Paid plan required; the only recurring cost is the domain. (The Campfire voice is the one paid model, Deepgram Aura-2, and it's pre-baked to static audio so there's $0 per-use spend.)

Turnstile

Invisible verification

Try the live demo →

How it works

One script tag in your form, one check on your server. No infrastructure to run.

👤
Visitor
your form
loads
🛡️
Turnstile
Cloudflare edge
token
🖥️
Your server
/siteverify
Verified → allowed
Failed → blocked

Add it to your site

~10 lines · no infrastructure
Client: drop into your form
<script src="https://challenges.cloudflare.com/turnstile/v0/api.js" defer></script>
<div class="cf-turnstile" data-sitekey="YOUR_SITEKEY"></div>
Server: verify the token on submit
const r = await fetch('https://challenges.cloudflare.com/turnstile/v0/siteverify', {
  method: 'POST',
  body: new URLSearchParams({ secret: env.TURNSTILE_SECRET, response: token }),
}).then((res) => res.json());

if (!r.success) return new Response('Blocked', { status: 403 });
01
Paste the widget into your form
02
Verify the token when the form submits
03
Ship. There is nothing to host.
Works with:Static HTMLNext.jsWordPressAny backend

Workers

AI-crawler control

Try the live demo →

How it works

Identify AI crawlers at the edge and decide per-caller: allow, charge, or block.

🤖
Caller
by User-Agent
request
🌐
Cloudflare edge
classify
Human → allowed
AI training → 402 license
Disallowed bot → 403

Add it to your site

1 dashboard toggle, or ~15 lines
No code: Cloudflare dashboard
Security → Bots → "Block AI bots" / "Pay per crawl"
One toggle. Cloudflare maintains the crawler signatures for you.
Custom policy: a Worker
const ua = request.headers.get('user-agent') || '';
const bot = classifyAiCrawler(ua); // GPTBot, ClaudeBot, CCBot, PerplexityBot…

if (bot?.policy === 'block')   return new Response('Forbidden', { status: 403 });
if (bot?.policy === 'license') return new Response('Payment required', { status: 402 });
return fetch(request); // humans pass straight through
01
Flip the AI-bots toggle in the dashboard (zero code)
02
Or deploy a Worker for custom allow / charge / block
03
Read the analytics: see exactly who is crawling you
Works with:Any site on CloudflareWorkersPages

D1

Data residency

Try the live demo →

How it works

Route each write to the data store in the visitor's own jurisdiction, decided at the edge.

👤
Visitor
write
POST
Worker
reads request.cf.country
route
🇪🇺 EU → D1 Dublin
🇺🇸 Else → D1 N. Virginia

Add it to your site

~20 lines + 2 D1 bindings
Worker: route by jurisdiction
const country = request.cf.country;          // free, at the edge
const eu = ['DE', 'FR', 'IE', 'NL' /* …EEA */];
const db = eu.includes(country) ? env.RESIDENCY_EU : env.RESIDENCY_US;

await db.prepare('INSERT INTO records (data) VALUES (?)').bind(payload).run();
wrangler.jsonc: two located databases
"d1_databases": [
  { "binding": "RESIDENCY_EU", "database_name": "app-eu" }, // created --jurisdiction eu (guaranteed EU)
  { "binding": "RESIDENCY_US", "database_name": "app-us" }  //         --location enam (US placement hint)
]
01
Create the EU database with --jurisdiction eu (guaranteed placement for GDPR), the US one with a location hint
02
Bind both in wrangler
03
Route on request.cf.country, resolved at the edge, no geo-IP service
Works with:WorkersPages FunctionsD1

AI Search (AutoRAG)

Grounded trust assistant

Try the live demo →

How it works

Point AI Search at your docs; it answers with citations, or refuses when the answer is not there.

💬
Question
from a user
query
Worker
aiSearch()
retrieve + generate
📚
AI Search
corpus + LLM
Grounded answer + citations
Not in docs → refuses

Add it to your site

dashboard setup + ~15 lines
Dashboard: create an AI Search instance
AI → AI Search → New
Data source: your R2 bucket or uploaded docs
Cloudflare chunks, embeds, and indexes them for you.
Worker: one call
const res = await env.AI.autorag('your-instance').aiSearch({
  query: question,
});

return Response.json({ answer: res.response, citations: res.data });
01
Create an AI Search instance pointed at your docs
02
Call aiSearch() from a Worker
03
Render the answer + citations; refusals come from your system prompt
Works with:Workers AIAI Search (AutoRAG)R2

Rate Limiting

Rate-limited floods

Try the live demo →

How it works

A Rate Limiting binding throttles abusive callers at the edge, before they ever reach origin.

🐎
Callers
logins / forms / API
request
🚦
Rate Limiting
Cloudflare edge
under limit
🖥️
Your origin
only clean traffic
Within limit → 200
Over limit → 429

Add it to your site

1 binding · a few lines
wrangler.jsonc: declare the limiter
"ratelimits": [
  { "name": "STAMPEDE_LIMITER", "namespace_id": "1001",
    "simple": { "limit": 5, "period": 10 } }
]
Worker: check it per request
const ip = request.headers.get('CF-Connecting-IP') ?? 'anon';
const { success } = await env.STAMPEDE_LIMITER.limit({ key: ip });
if (!success) return new Response('Slow down', { status: 429 });
01
Declare a Rate Limiting binding (limit / period)
02
Call .limit({ key }) at the top of the request
03
Return 429 when the window is exceeded
Works with:WorkersPages FunctionsAny edge route

Cache / CDN

Edge caching

Try the live demo →

How it works

Cache the rendered response at the edge so the first visitor pays the cost once and everyone after is instant.

👥
Readers
worldwide
request
Edge cache
Cache API
on MISS
🖥️
Origin render
only on MISS
First hit → MISS (~700ms)
Every hit after → HIT (~5ms)

Add it to your site

~8 lines · no infrastructure
Worker: cache-aside with the Cache API
const cache = caches.default;
let res = await cache.match(request);          // HIT?
if (!res) {
  res = await renderExpensive();               // MISS: pay once
  res.headers.set('Cache-Control', 'public, max-age=60');
  ctx.waitUntil(cache.put(request, res.clone()));
}
return res;
01
Look the request up in the edge cache
02
On MISS, render once and store it with a Cache-Control TTL
03
Serve every subsequent reader the cached copy
Works with:WorkersPages FunctionsCache Rules (no code)

Official Cloudflare docs

D1 (atomic)

Atomic inventory

Try the live demo →

How it works

A single atomic D1 write guards the stock count, so concurrent buyers can never race it below zero.

🛒
Buyers + bots
all at once
buy
🗄️
D1 atomic UPDATE
qty > 0 guard
one statement
Fair result
no oversell
Stock left → bought
Zero left → sold out

Add it to your site

1 SQL statement · no race
D1: decrement only if stock remains
const { meta } = await env.DB.prepare(
  'UPDATE stock SET qty = qty - 1 WHERE id = ?1 AND qty > 0'
).bind(productId).run();

const bought = meta.changes === 1;   // 0 changes = sold out, no oversell
01
Keep the count in one D1 row
02
Decrement with a single guarded UPDATE (qty > 0)
03
Use rows-changed to tell "bought" from "sold out"
Works with:D1Pages FunctionsAny SQL backend

D1 · Pages Functions

Regulated messaging

Try the live demo →

How it works

Consent and quiet-hours enforced at send time, with every decision written to an append-only audit trail.

📣
Dispatch
outage alert
send
Worker
consent + quiet-hours gate
check + log
🗄️
D1
ledger + audit log
Consented + daytime → sent
Quiet hours → held
Opted out → blocked

Add it to your site

D1 · gated + fully audited
Gate each send on consent + local quiet-hours
const localHour = ((sendHourUtc + r.tz_offset) % 24 + 24) % 24;
let decision;
if (!r.opted_in)                            decision = 'blocked';    // no consent (TCPA)
else if (localHour < 8 || localHour >= 21)  decision = 'suppressed'; // quiet hours
else                                        decision = 'sent';
Write an immutable audit row for every decision
await env.DISPATCH_DB.prepare(
  'INSERT INTO dispatch_audit (id, batch_id, recipient_id, decision, reason, created_at) VALUES (?, ?, ?, ?, ?, ?)'
).bind(id, batchId, r.recipient_id, decision, reason, new Date().toISOString()).run();
// rows are only ever inserted, never updated or deleted
01
Keep a consent ledger (opt-in/out per recipient and channel) in D1
02
Gate every send on consent and the recipient's local quiet-hours
03
Append one immutable audit row per decision: the regulator-evidence trail
Works with:D1Pages FunctionsAny regulated-comms workflow

Workers AI · pre-baked static

Campfire joke bot

How it works

A joke bot whose voice runs on Cloudflare. Generated once with Workers AI, then served as static audio for $0 per use.

🤖
Workers AI
Llama 3.3 70B
writes joke
🗣️
Aura-2 TTS
voices it
baked once
📦
Static files
on Pages
served
Setup → spoken
Punchline → on reveal

Add it to your site

pre-baked → $0 per use
Generate the line (Workers AI · Llama)
const r = await env.AI.run('@cf/meta/llama-3.3-70b-instruct-fp8-fast', {
  messages: [{ role: 'system', content: COWBOY_PROMPT }, { role: 'user', content: 'Tell me a joke.' }],
});
Voice it once (Deepgram Aura-2)
const audio = await env.AI.run('@cf/deepgram/aura-2-en', { text, speaker: 'zeus' });
// baked to /cowboy/jokes/<id>-zeus-<line>.mp3 -> served static, no per-use spend
01
Generate the joke pool with Workers AI (Llama)
02
Voice each line once with Deepgram Aura-2 (TTS)
03
Ship the audio as static files: $0 recurring, instant playback
Works with:Workers AIDeepgram Aura-2Pages (static)

D1

Defend the Edge leaderboard

Try the live demo →

How it works

A global leaderboard on D1: every submit is one atomic insert, with hashed-IP rate limiting at the edge.

🎯
Player
submits score
POST
Worker
rate-limit
check
🗄️
D1
atomic INSERT
insert
Saved → rank returned
Too many → 429

Add it to your site

D1 · no read-modify-write race
Atomic insert (no lost-update race)
await env.LEADERBOARD_DB
  .prepare('INSERT INTO leaderboard_scores (name, score, ip_hash, ts) VALUES (?, ?, ?, ?)')
  .bind(name, score, ipHash, ts).run();
Edge rate-limit (privacy-safe)
const ipHash = await sha256(request.headers.get('CF-Connecting-IP')); // never store raw IP
const recent = await db.prepare('SELECT COUNT(*) c FROM leaderboard_scores WHERE ip_hash=? AND ts>?')
  .bind(ipHash, Date.now() - 60_000).first();
if (recent.c >= 8) return json({ ok: false, error: 'rate limited' }, 429);
01
Create a D1 database for scores
02
INSERT per submit: atomic, so concurrent writes never clobber
03
Rate-limit per hashed IP to stop flooding
Works with:D1Pages FunctionsWeb Crypto