Skip to main content

Cloudflare Developer Cheat Sheet

Quick reference for all Cloudflare services you can use during the workshop.


Workers - Serverless Compute

What: Run code at the edge, globally. JavaScript, TypeScript, Python, Rust.

// Basic Worker (src/index.ts)
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);

if (url.pathname === '/api/hello') {
return Response.json({ message: 'Hello from the edge!' });
}

return new Response('Not found', { status: 404 });
},
};

Routing pattern:

export default {
async fetch(request: Request, env: Env): Promise<Response> {
const url = new URL(request.url);
const { pathname } = url;
const method = request.method;

// REST-style routing
if (method === 'GET' && pathname === '/api/items') {
return handleListItems(env);
}
if (method === 'POST' && pathname === '/api/items') {
const body = await request.json();
return handleCreateItem(env, body);
}
if (method === 'GET' && pathname.startsWith('/api/items/')) {
const id = pathname.split('/').pop();
return handleGetItem(env, id);
}

return new Response('Not found', { status: 404 });
},
};

CORS helper:

function corsHeaders(): HeadersInit {
return {
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type',
};
}

// Use in responses
return new Response(JSON.stringify(data), {
headers: { 'Content-Type': 'application/json', ...corsHeaders() },
});

// Handle preflight
if (request.method === 'OPTIONS') {
return new Response(null, { headers: corsHeaders() });
}

D1 - SQL Database

What: SQLite on the edge. Serverless, zero-config.

Setup:

npx wrangler d1 create my-db
# Add binding to wrangler.jsonc
npx wrangler d1 execute my-db --remote --file=schema.sql

Common operations:

// SELECT multiple rows
const { results } = await env.DB.prepare(
'SELECT * FROM items ORDER BY created_at DESC LIMIT ?'
).bind(20).all();

// SELECT single row
const item = await env.DB.prepare(
'SELECT * FROM items WHERE id = ?'
).bind(id).first();

// INSERT
const result = await env.DB.prepare(
'INSERT INTO items (title, content) VALUES (?, ?)'
).bind(title, content).run();
// result.meta.last_row_id gives you the new ID

// UPDATE
await env.DB.prepare(
'UPDATE items SET title = ?, content = ? WHERE id = ?'
).bind(title, content, id).run();

// DELETE
await env.DB.prepare('DELETE FROM items WHERE id = ?').bind(id).run();

// Batch operations
const results = await env.DB.batch([
env.DB.prepare('INSERT INTO items (title) VALUES (?)').bind('Item 1'),
env.DB.prepare('INSERT INTO items (title) VALUES (?)').bind('Item 2'),
]);

R2 - Object Storage

What: S3-compatible storage with zero egress fees.

Setup:

npx wrangler r2 bucket create my-bucket
# Add binding to wrangler.jsonc

Common operations:

// Upload a file
await env.BUCKET.put('photos/cat.jpg', imageData, {
httpMetadata: { contentType: 'image/jpeg' },
customMetadata: { uploadedBy: 'user123' },
});

// Download a file
const object = await env.BUCKET.get('photos/cat.jpg');
if (object) {
return new Response(object.body, {
headers: { 'Content-Type': object.httpMetadata?.contentType || '' },
});
}

// List files
const listed = await env.BUCKET.list({ prefix: 'photos/', limit: 100 });
const files = listed.objects.map(obj => ({
key: obj.key,
size: obj.size,
uploaded: obj.uploaded,
}));

// Delete a file
await env.BUCKET.delete('photos/cat.jpg');

// Handle multipart upload from a form
const formData = await request.formData();
const file = formData.get('file') as File;
await env.BUCKET.put(file.name, file.stream(), {
httpMetadata: { contentType: file.type },
});

KV - Key-Value Storage

What: Global, low-latency key-value store. Eventually consistent.

npx wrangler kv namespace create MY_KV
# Add binding to wrangler.jsonc
// Set a value (with optional TTL)
await env.MY_KV.put('user:123', JSON.stringify({ name: 'Alice' }));
await env.MY_KV.put('session:abc', 'data', { expirationTtl: 3600 });

// Get a value
const data = await env.MY_KV.get('user:123', 'json');

// Delete
await env.MY_KV.delete('user:123');

// List keys
const keys = await env.MY_KV.list({ prefix: 'user:' });

Workers AI - Run AI Models

What: Run inference on Cloudflare's GPU network. No setup needed.

Add "ai": { "binding": "AI" } to wrangler.jsonc.

// Text generation (LLM)
const response = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [
{ role: 'system', content: 'You are a helpful assistant.' },
{ role: 'user', content: 'What is Cloudflare?' },
],
});
// response.response = "Cloudflare is..."

// Streaming response
const stream = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', {
messages: [{ role: 'user', content: 'Tell me a story' }],
stream: true,
});
return new Response(stream, {
headers: { 'Content-Type': 'text/event-stream' },
});

// Text-to-image
const image = await env.AI.run(
'@cf/stabilityai/stable-diffusion-xl-base-1.0',
{ prompt: 'a sunset over Stockholm' }
);
return new Response(image, {
headers: { 'Content-Type': 'image/png' },
});

// Embeddings (for semantic search)
const embeddings = await env.AI.run('@cf/baai/bge-base-en-v1.5', {
text: ['text to embed'],
});

// Translation
const translated = await env.AI.run('@cf/meta/m2m100-1.2b', {
text: 'Hello, how are you?',
source_lang: 'english',
target_lang: 'swedish',
});

// Summarization
const summary = await env.AI.run('@cf/facebook/bart-large-cnn', {
input_text: longArticleText,
max_length: 200,
});

Popular models:

  • @cf/meta/llama-3.1-8b-instruct - Text generation
  • @cf/meta/llama-3.1-70b-instruct - Larger text generation
  • @cf/baai/bge-base-en-v1.5 - Text embeddings
  • @cf/stabilityai/stable-diffusion-xl-base-1.0 - Image generation
  • @cf/microsoft/resnet-50 - Image classification
  • @cf/meta/m2m100-1.2b - Translation
  • @cf/facebook/bart-large-cnn - Summarization

Full model list: developers.cloudflare.com/workers-ai/models/


Durable Objects - Stateful Edge

What: Single-instance, stateful objects. Perfect for real-time, coordination, and sessions.

// In wrangler.jsonc
{
"durable_objects": {
"bindings": [{ "name": "ROOMS", "class_name": "ChatRoom" }]
},
"migrations": [{ "tag": "v1", "new_classes": ["ChatRoom"] }]
}
// Durable Object class
export class ChatRoom {
state: DurableObjectState;
sessions: WebSocket[] = [];

constructor(state: DurableObjectState) {
this.state = state;
}

async fetch(request: Request): Promise<Response> {
// Handle WebSocket upgrade for real-time
const { 0: client, 1: server } = new WebSocketPair();
server.accept();
this.sessions.push(server);

server.addEventListener('message', (event) => {
// Broadcast to all connected clients
for (const session of this.sessions) {
session.send(event.data);
}
});

return new Response(null, { status: 101, webSocket: client });
}
}

// In your main Worker, route to the DO
const id = env.ROOMS.idFromName('room-1');
const room = env.ROOMS.get(id);
return room.fetch(request);

Quick wrangler.jsonc Template

{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "my-project",
"main": "src/index.ts",
"compatibility_date": "2025-05-19",
"compatibility_flags": ["nodejs_compat"],

// Uncomment what you need:

// "d1_databases": [{
// "binding": "DB",
// "database_name": "my-db",
// "database_id": "your-id-here"
// }],

// "r2_buckets": [{
// "binding": "BUCKET",
// "bucket_name": "my-bucket"
// }],

// "kv_namespaces": [{
// "binding": "KV",
// "id": "your-id-here"
// }],

// "ai": { "binding": "AI" },

"observability": { "enabled": true }
}

Env type definition:

interface Env {
DB: D1Database;
BUCKET: R2Bucket;
KV: KVNamespace;
AI: Ai;
ROOMS: DurableObjectNamespace;
}