Cloudflare Workers is a serverless platform for building, deploying, and scaling applications across Cloudflare's global network with a single command and no infrastructure to manage.
Core Concepts
Edge Computing: Code runs at locations closest to users for minimal latency
Create your first Cloudflare Worker and understand the fundamentals of serverless edge computing. Learn about the Workers runtime and deploy your first function.
🎯 Learning Objectives
Create and deploy your first Cloudflare Worker
Understand the Workers runtime environment
Learn about edge computing concepts
Test your Worker using Wrangler CLI
🛠️Understanding Cloudflare Workers
Cloudflare Workers is a serverless platform for building, deploying, and scaling applications across Cloudflare’s global network with a single command and no infrastructure to manage.
Edge Computing: Code runs at locations closest to users for minimal latency
Global Network: Deploy once, run everywhere across Cloudflare’s infrastructure
Serverless: No servers to manage, automatic scaling, pay-per-request
Watch: Cloudflare Workers 101
Before diving into the hands-on tutorial, watch this comprehensive overview to understand the core concepts and architecture of Cloudflare Workers. This video covers the fundamentals that will help you better understand building with Cloudflare Workers.
Step 1: Create Your First Worker
What we're building
A simple Cloudflare Worker that responds to HTTP requests with a custom message.
Why this matters
Workers handle HTTP requests at the edge, providing fast responses to users worldwide with minimal setup.
# Create a new Worker project with TypeScriptnpm create cloudflare@latest -- my-first-worker --type hello-world --ts# Navigate to your projectcd my-first-worker# Start development servernpx wrangler dev
Expected Outputtext
⎔ Starting local server…
[wrangler:info] Ready on http://localhost:8787
🌍 Your Worker is running locally and ready for testing
📝 Edit src/index.ts to see changes in real-time
📝What Just Happened?
You’ve created a Cloudflare Worker that includes:
HTTP Handler: Function that processes incoming requests
Local Development: Wrangler dev server for testing
Hot Reloading: Changes reflect immediately during development
Troubleshooting
npm not found: Install Node.js v20+ from nodejs.org
Template not found: Update npm: npm install -g npm@latest
Port 8787 busy: Stop other services or use npm run dev -- --port 8788
Build errors: Delete node_modules and run npm install again
Step 2: Understanding Your Worker Code
What we're building
Understanding of your Worker's code structure and how it processes HTTP requests.
Why this matters
Understanding the fetch handler is fundamental to building any application with Cloudflare Workers.
Let’s examine the default Worker code that was generated:
Every Cloudflare Worker exports a default object with handler functions:
fetch: Handles HTTP requests (required for web applications)
scheduled: Handles cron triggers (optional)
queue: Handles queue messages (optional)
email: Handles email events (optional)
The Fetch Handler Parameters:
request: Contains the incoming HTTP request (URL, headers, method, body)
env: Environment variables and bindings (KV, R2, D1, etc.)
ctx: Context object with waitUntil() and passThroughOnException()
Step 3: Test Your Worker
What we're building
A working local development environment where you can test your Worker and see changes in real-time.
Why this matters
Local testing is essential for rapid development and debugging before deploying to production.
Testing Your Worker:
Open your browser and navigate to http://localhost:8787
You should see: “Hello World!” displayed in your browser
Try different URLs like http://localhost:8787/test - same response
Check the terminal for request logs showing method, path, and response time
📝What You Should See
Your terminal will show logs like:
GET / 200 OK (2ms) - successful request
Hot reloading when you save file changes
Any console.log() output from your Worker
Step 4: Deploy to Production
What we're building
Your first Worker deployed to Cloudflare's global network, accessible via a workers.dev subdomain.
Why this matters
Deploying to production lets you see your Worker running at the edge across Cloudflare's global network.
# Deploy your Worker to productionnpx wrangler deploy
After deployment, you’ll see:
Your Worker URL:https://my-first-worker.<your-subdomain>.workers.dev
Global deployment across 300+ data centers
Instant availability worldwide
📝Production Deployment
Your Worker is now running on Cloudflare’s global network:
Global reach: Available from 300+ locations worldwide
Automatic scaling: Handles traffic spikes without configuration
Zero cold starts: V8 isolates start instantly
Built-in security: DDoS protection and security features included
✅ Congratulations! You’ve created and deployed your first Cloudflare Worker. You’re ready to learn HTTP request handling in Step 2!
STEP 02
HTTP Request Handling
Learn how to handle HTTP requests in Cloudflare Workers using the fetch handler, parse URLs, and work with different HTTP methods.
🎯 Learning Objectives
Understand the Workers fetch handler
Parse and work with Request objects
Handle different HTTP methods
Create dynamic responses based on URL paths
📝Understanding HTTP in Workers
Cloudflare Workers use the fetch handler to process incoming HTTP requests. Every request is passed as a Request object, and you must return a Response object.
Request Object: Contains URL, headers, method, and body
Response Object: Your Worker’s reply with status, headers, and content
URL Parsing: Extract paths, query parameters, and routing logic
HTTP Methods: Handle GET, POST, PUT, DELETE, and more
Step 1: Basic Fetch Handler
What we're building
A Worker that handles HTTP requests and returns different responses based on the request.
Why this matters
The fetch handler is the foundation of all HTTP processing in Workers - understanding it is essential for building web applications.
📝 Instructions:
Open your Worker project from Step 1
Navigate to src/index.ts
Replace the existing code with a more comprehensive fetch handler
export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> { // Get the URL from the request const url = new URL(request.url); // Basic routing based on pathname if (url.pathname === '/') { return new Response('Welcome to my Worker!', { headers: { 'Content-Type': 'text/plain' } }); } if (url.pathname === '/hello') { return new Response('Hello, World!', { headers: { 'Content-Type': 'text/plain' } }); } // Return 404 for unknown paths return new Response('Not Found', { status: 404, headers: { 'Content-Type': 'text/plain' } }); }};
📝Understanding the Parameters
The fetch handler receives three parameters:
request: The incoming HTTP request object
env: Environment variables and bindings
ctx: Context object with waitUntil and passThroughOnException methods
Step 2: Handle Different HTTP Methods
What we're building
A Worker that responds differently to GET, POST, PUT, and DELETE requests.
Why this matters
Real applications need to handle various HTTP methods for different operations like reading data (GET) and creating resources (POST).
Update your Worker to handle different HTTP methods:
export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> { const url = new URL(request.url); const method = request.method; // Handle different paths and methods if (url.pathname === '/api/data') { switch (method) { case 'GET': const getResponse = { message: 'Getting data', timestamp: new Date().toISOString() }; const logEntry = { message: 'Getting data', timestamp: new Date().toISOString() }; return new Response(JSON.stringify(getResponse), { headers: { 'Content-Type': 'application/json' } }); case 'POST': // Read the request body const body = await request.text(); const postResponse = { message: 'Data received', received: body, timestamp: new Date().toISOString() }; return new Response(JSON.stringify(postResponse), { headers: { 'Content-Type': 'application/json' } }); case 'PUT': const putResponse = { message: 'Data updated', timestamp: new Date().toISOString() }; return new Response(JSON.stringify(putResponse), { headers: { 'Content-Type': 'application/json' } }); case 'DELETE': const deleteResponse = { message: 'Data deleted', timestamp: new Date().toISOString() }; return new Response(JSON.stringify(deleteResponse), { headers: { 'Content-Type': 'application/json' } }); default: return new Response('Method not allowed', { status: 405, headers: { 'Allow': 'GET, POST, PUT, DELETE' } }); } } // Default response return new Response('Worker is running!', { headers: { 'Content-Type': 'text/plain' } }); }};
Step 3: URL Parameters and Query Strings
What we're building
A Worker that extracts and uses URL parameters and query strings to create dynamic responses.
Why this matters
Dynamic routing and parameter extraction are essential for building flexible APIs and web applications.
GET http://localhost:8787/search?q=cloudflare&limit=5
GET http://localhost:8787/search - Should return error for missing query
Path Parameters:
GET http://localhost:8787/users/john - Returns user profile for “john”
GET http://localhost:8787/users/123 - Returns user profile for “123”
Headers:
GET http://localhost:8787/headers - Returns all request headers
Using HTTPie for Testing:
Note: Install HTTPie once, then reuse these commands throughout the workshop.
macOS: brew install httpie
Windows: winget install HTTPie.HTTPie
Any OS (Python): pipx install httpie
# Test GET requesthttp http://localhost:8787/api/data# Test POST request with JSON bodyhttp POST http://localhost:8787/api/data message="Hello from HTTPie"# Test with query parametershttp "http://localhost:8787/search?q=workers&limit=3"# Test path parametershttp http://localhost:8787/users/alice
📝What You Should See
JSON Responses: Properly formatted JSON with timestamps
Status Codes: 200 for success, 404 for not found, 405 for wrong method
Dynamic Content: Responses change based on URL parameters and request data
Header Handling: Request headers are properly parsed and returned
✅ Great work! You’ve mastered HTTP request handling in Workers. Ready to add persistent storage with Workers KV in Step 3!
STEP 03
Workers KV Storage
Learn to use Cloudflare Workers KV for persistent data storage. Build a simple key-value API with global, low-latency storage.
🎯 Learning Objectives
Create and configure Cloudflare KV namespaces
Implement CRUD operations with KV storage
Handle storage operations and errors
Build stateful applications with persistent data
📝Persistent Storage with KV
Cloudflare Workers KV provides global, low-latency key-value storage that’s perfect for configuration, user preferences, and caching data.
Global Distribution: Data replicated across Cloudflare’s network
Eventually Consistent: Fast reads with eventual consistency
Generous Limits: 1GB storage and 100,000 operations daily on free tier
Storage operations: Return success messages with 201 status
Retrieval: Return stored values in JSON format
List operations: Return arrays of keys or user IDs
Error handling: Graceful responses for missing keys or errors
⚠️KV Consistency
Remember that KV is eventually consistent. Changes may take a few seconds to propagate globally. In local development, changes are typically immediate.
✅ Excellent work! You’ve learned to use Workers KV for persistent storage with advanced features. Ready for more advanced Workers features in Step 4!
STEP 04
D1 Database Integration
Learn to use Cloudflare D1 for relational data storage. Build a REST API with SQL database operations and understand serverless SQL.
🎯 Learning Objectives
Create and configure Cloudflare D1 databases
Implement CRUD operations with SQL queries
Build REST API endpoints with database integration
Handle database transactions and error management
🌐Cloudflare D1 Database
D1 is Cloudflare’s native serverless SQL database built on SQLite. It provides familiar SQL operations with global distribution and automatic scaling.
Serverless SQL: Full SQL database without server management
Global Distribution: Data replicated across Cloudflare’s network
SQLite Compatible: Use familiar SQL syntax and operations
Worker Integration: Direct binding to your Workers for low-latency access
Step 1: Create Your First D1 Database
What we're building
A D1 database configured and connected to your Worker for storing relational data.
Why this matters
D1 provides structured data storage with SQL queries, perfect for complex data relationships and transactions.
📝 Create the Database
Create a new D1 database:
npx wrangler d1 create my-blog-db
Copy the configuration output and add to your wrangler.jsonc:
A database schema with tables for a simple blog application with posts and comments.
Why this matters
Proper schema design is crucial for relational databases and demonstrates SQL DDL operations.
📝 Create Schema File
Create a schema.sql file in your project root:
-- Drop tables if they exist (for development)DROP TABLE IF EXISTS comments;DROP TABLE IF EXISTS posts;-- Create posts tableCREATE TABLE posts ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, content TEXT NOT NULL, author TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, updated_at DATETIME DEFAULT CURRENT_TIMESTAMP);-- Create comments tableCREATE TABLE comments ( id INTEGER PRIMARY KEY AUTOINCREMENT, post_id INTEGER NOT NULL, author TEXT NOT NULL, content TEXT NOT NULL, created_at DATETIME DEFAULT CURRENT_TIMESTAMP, FOREIGN KEY (post_id) REFERENCES posts (id) ON DELETE CASCADE);-- Insert sample dataINSERT INTO posts (title, content, author) VALUES ('Getting Started with D1', 'D1 is Cloudflare''s serverless SQL database...', 'CloudflareTeam'), ('Building with Workers', 'Workers provide serverless compute at the edge...', 'DevRel'), ('SQL at the Edge', 'Running SQL queries globally distributed...', 'Engineering');INSERT INTO comments (post_id, author, content) VALUES (1, 'Developer1', 'Great introduction to D1!'), (1, 'Developer2', 'Looking forward to trying this out.'), (2, 'Developer3', 'Workers are amazing for edge computing.');
📝 Apply Schema
# Apply schema to local development databasenpx wrangler d1 execute my-blog-db --local --file=./schema.sql# Apply schema to production databasenpx wrangler d1 execute my-blog-db --file=./schema.sql
Step 3: Build REST API with D1
What we're building
A complete REST API for blog posts and comments using D1 database operations.
Why this matters
Demonstrates real-world database integration patterns with proper error handling and SQL best practices.
📝 Create Your Worker
Update your src/index.ts:
const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type',};export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> { const url = new URL(request.url); const { pathname } = url; // CORS headers for browser requests // Handle CORS preflight requests if (request.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders }); } try { // Route handling if (pathname === '/posts' && request.method === 'GET') { return await getPosts(env.DB, corsHeaders); } if (pathname === '/posts' && request.method === 'POST') { return await createPost(request, env.DB, corsHeaders); } if (pathname.startsWith('/posts/') && request.method === 'GET') { const postId = pathname.split('/')[2]; return await getPost(postId, env.DB, corsHeaders); } if (pathname.startsWith('/posts/') && pathname.endsWith('/comments') && request.method === 'GET') { const postId = pathname.split('/')[2]; return await getComments(postId, env.DB, corsHeaders); } if (pathname.startsWith('/posts/') && pathname.endsWith('/comments') && request.method === 'POST') { const postId = pathname.split('/')[2]; return await createComment(request, postId, env.DB, corsHeaders); } return new Response('Not Found', { status: 404, headers: corsHeaders }); } catch (error: any) { console.error('Error:', error); return new Response('Internal Server Error', { status: 500, headers: corsHeaders }); } },};// Get all postsasync function getPosts(db, corsHeaders) { const { results } = await db.prepare(` SELECT id, title, content, author, created_at, updated_at FROM posts ORDER BY created_at DESC `).all(); return new Response(JSON.stringify(results), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } });}// Create a new postasync function createPost(request, db, corsHeaders) { const { title, content, author } = await request.json(); if (!title || !content || !author) { return new Response('Missing required fields', { status: 400, headers: corsHeaders }); } const { results } = await db.prepare(` INSERT INTO posts (title, content, author) VALUES (?, ?, ?) RETURNING id, title, content, author, created_at, updated_at `).bind(title, content, author).all(); return new Response(JSON.stringify(results[0]), { status: 201, headers: { ...corsHeaders, 'Content-Type': 'application/json' } });}// Get a specific postasync function getPost(postId: string, db: D1Database, corsHeaders: CorsHeaders): Promise<Response> { const { results } = await db.prepare(` SELECT id, title, content, author, created_at, updated_at FROM posts WHERE id = ? `).bind(postId).all(); if (results.length === 0) { return new Response('Post not found', { status: 404, headers: corsHeaders }); } return new Response(JSON.stringify(results[0]), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } });}// Get comments for a postasync function getComments(postId, db, corsHeaders) { const { results } = await db.prepare(` SELECT id, author, content, created_at FROM comments WHERE post_id = ? ORDER BY created_at ASC `).bind(postId).all(); return new Response(JSON.stringify(results), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } });}// Create a commentasync function createComment(request, postId, db, corsHeaders) { const { author, content } = await request.json(); if (!author || !content) { return new Response('Missing required fields', { status: 400, headers: corsHeaders }); } // Check if post exists const { results: postCheck } = await db.prepare(` SELECT id FROM posts WHERE id = ? `).bind(postId).all(); if (postCheck.length === 0) { return new Response('Post not found', { status: 404, headers: corsHeaders }); } const { results } = await db.prepare(` INSERT INTO comments (post_id, author, content) VALUES (?, ?, ?) RETURNING id, author, content, created_at `).bind(postId, author, content).all(); return new Response(JSON.stringify(results[0]), { status: 201, headers: { ...corsHeaders, 'Content-Type': 'application/json' } });}
Step 4: Test Your D1 API
What we're building
A fully functional blog API with posts and comments that you can test locally and deploy globally.
Why this matters
Testing ensures your database operations work correctly and demonstrates the complete development workflow.
📝 Local Development
Start local development:
npx wrangler dev --local
Test the API endpoints:
# Get all postshttp http://localhost:8787/posts# Create a new posthttp POST http://localhost:8787/posts \ title="My New Post" \ content="This is the content" \ author="YourName"# Get a specific posthttp http://localhost:8787/posts/1# Get comments for a posthttp http://localhost:8787/posts/1/comments# Create a commenthttp POST http://localhost:8787/posts/1/comments \ author="Commenter" \ content="Great post!"
📝 Deploy to Production
npx wrangler deploy
✅
🎉 Congratulations! You’ve built a complete REST API with D1 database integration. Your API supports full CRUD operations for posts and comments with proper error handling and CORS support.
Key Takeaways
D1 Integration: Seamless SQL database binding to Workers
A fully deployed AI-powered Worker with comprehensive testing of all AI capabilities.
Why this matters
Testing ensures your AI integrations work correctly and handle edge cases gracefully.
Deploy Your AI Worker
# Deploy to Cloudflarenpx wrangler deploy# Test all endpointshttp https://your-worker.your-subdomain.workers.dev/
Testing Checklist
💡AI Testing Strategy
Test these scenarios to ensure robust AI integration:
Text Generation: Various prompt lengths and complexity
Image Analysis: Different image formats and sizes
Error Handling: Invalid inputs and network failures
Rate Limits: High-frequency requests
Model Fallbacks: Alternative models when primary fails
# Test text generationhttp POST https://your-worker.your-subdomain.workers.dev/generate \ prompt="Explain quantum computing in simple terms"# Test sentiment analysishttp POST https://your-worker.your-subdomain.workers.dev/classify \ text="This is amazing!" task="sentiment"# Test chat interfaceopen https://your-worker.your-subdomain.workers.dev/
Production Considerations
🚀AI in Production
Consider these factors for production AI applications:
Rate Limiting: Implement request throttling to manage costs
Caching: Cache AI responses for repeated queries
Error Handling: Graceful fallbacks when models are unavailable
Monitoring: Track usage, latency, and error rates
Content Filtering: Implement safety measures for user-generated content
✅ Workers AI models integrated🧠 Text generation working👁️ Image analysis functional📊 Text classification active💬 Interactive chat interface deployed🚀 Ready for AI-powered applications!
✅ Outstanding work! You’ve successfully integrated Workers AI into your applications. Ready to learn about AI Gateway in Step 6!
STEP 06
AI Gateway Integration
Learn to use AI Gateway for managing, monitoring, and securing AI model requests. Build intelligent applications with request analytics and caching.
🎯 Learning Objectives
Create and configure AI Gateway for request management
Implement AI Gateway with Workers AI integration
Monitor AI usage with analytics and logging
Optimize AI requests with caching and rate limiting
🌐AI Gateway Overview
AI Gateway provides a unified interface to manage, monitor, and secure your AI model requests across different providers with built-in analytics, caching, and rate limiting.
Request Management: Route and manage AI requests efficiently
Analytics & Monitoring: Track usage, costs, and performance metrics
Caching: Reduce costs and latency with intelligent response caching
Rate Limiting: Control and protect your AI usage with request limits
Step 1: Create Your AI Gateway
What we're building
An AI Gateway configured to manage and monitor your Workers AI requests with analytics enabled.
Why this matters
AI Gateway provides essential observability and control over AI model usage, helping optimize costs and performance.
# Get your Account ID and create API token firsthttp POST "https://api.cloudflare.com/client/v4/accounts/{account_id}/ai-gateway/gateways" \ Authorization:"Bearer {api_token}" \ id="my-ai-gateway"
Step 2: Configure Worker with AI Gateway
What we're building
A Worker that routes AI requests through AI Gateway for monitoring and management.
Why this matters
Integration with AI Gateway provides request analytics, caching, and centralized AI model management.
export default { async fetch(request: Request, env: Env, ctx: ExecutionContext): Promise<Response> { const url = new URL(request.url); const { pathname } = url; // CORS headers const corsHeaders = { 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Methods': 'GET, POST, OPTIONS', 'Access-Control-Allow-Headers': 'Content-Type', }; if (request.method === 'OPTIONS') { return new Response(null, { headers: corsHeaders }); } try { // Route handling if (pathname === '/chat' && request.method === 'POST') { return await handleChat(request, env, corsHeaders); } if (pathname === '/summarize' && request.method === 'POST') { return await handleSummarize(request, env, corsHeaders); } if (pathname === '/translate' && request.method === 'POST') { return await handleTranslate(request, env, corsHeaders); } if (pathname === '/health' && request.method === 'GET') { const healthResponse = { status: 'healthy', gateway: 'active' }; return new Response(JSON.stringify(healthResponse), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } }); } return new Response('Not Found', { status: 404, headers: corsHeaders }); } catch (error: any) { console.error('Error:', error); const errorResponse = { error: 'Internal Server Error' }; return new Response(JSON.stringify(errorResponse), { status: 500, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }); } },};// Chat completion with AI Gatewayasync function handleChat(request: Request, env: Env, corsHeaders: CorsHeaders): Promise<Response> { const { message, model = '@cf/meta/llama-3.1-8b-instruct' } = await request.json(); if (!message) { const errorResponse = { error: 'Message is required' }; return new Response(JSON.stringify(errorResponse), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }); } // Use AI Gateway for request routing and monitoring const response = await env.AI.run(model, { messages: [ { role: 'system', content: 'You are a helpful assistant.' }, { role: 'user', content: message } ] }, { gateway: { id: env.GATEWAY_ID, skipCache: false, cacheTtl: 3600 // Cache for 1 hour } }); const chatResponse = { response: response.response, model: model, cached: response.cached || false }; return new Response(JSON.stringify(chatResponse), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } });}// Text summarization with cachingasync function handleSummarize(request: Request, env: Env, corsHeaders: CorsHeaders): Promise<Response> { const { text, maxLength = 100 } = await request.json(); if (!text) { const errorResponse = { error: 'Text is required' }; return new Response(JSON.stringify(errorResponse), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }); } const prompt = `Summarize the following text in ${maxLength} words or less:\n\n${text}`; const response = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', { messages: [{ role: 'user', content: prompt }] }, { gateway: { id: env.GATEWAY_ID, skipCache: false, cacheTtl: 7200 // Cache for 2 hours } }); const summarizeResponse = { summary: response.response, originalLength: text.length, summaryLength: response.response.length, cached: response.cached || false }; return new Response(JSON.stringify(summarizeResponse), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } });}// Language translationasync function handleTranslate(request: Request, env: Env, corsHeaders: CorsHeaders): Promise<Response> { const { text, targetLanguage, sourceLanguage = 'auto' } = await request.json(); if (!text || !targetLanguage) { const errorResponse = { error: 'Text and target language are required' }; return new Response(JSON.stringify(errorResponse), { status: 400, headers: { ...corsHeaders, 'Content-Type': 'application/json' } }); } const prompt = `Translate the following text to ${targetLanguage}. Only return the translation, no explanations:\n\n${text}`; const response = await env.AI.run('@cf/meta/llama-3.1-8b-instruct', { messages: [{ role: 'user', content: prompt }] }, { gateway: { id: env.GATEWAY_ID, skipCache: false, cacheTtl: 86400 // Cache for 24 hours } }); const translateResponse = { translation: response.response, sourceLanguage: sourceLanguage, targetLanguage: targetLanguage, cached: response.cached || false }; return new Response(JSON.stringify(translateResponse), { headers: { ...corsHeaders, 'Content-Type': 'application/json' } });}
Step 3: Test AI Gateway Integration
What we're building
A working AI Gateway setup with multiple AI endpoints that you can test and monitor.
Why this matters
Testing ensures proper integration and demonstrates the monitoring capabilities of AI Gateway.
📝 Local Development
npx wrangler dev --local
📝 Test API Endpoints
# Test chat endpointhttp POST http://localhost:8787/chat \ message="Explain Cloudflare Workers in simple terms"# Test summarization (use := to keep number type)http POST http://localhost:8787/summarize \ text="Cloudflare Workers is a serverless platform that allows developers to run JavaScript code at the edge, closer to users around the world. This reduces latency and improves performance for web applications. Workers can handle HTTP requests, process data, and integrate with various Cloudflare services like KV storage and D1 databases." \ maxLength:=50# Test translationhttp POST http://localhost:8787/translate \ text="Hello, how are you today?" \ targetLanguage="Spanish"# Health checkhttp http://localhost:8787/health
Step 4: Monitor and Optimize with AI Gateway
What we're building
Understanding of AI Gateway analytics and optimization features for managing AI usage effectively.
Why this matters
Monitoring helps optimize costs, performance, and reliability of AI-powered applications.
📝 Deploy and Monitor
Deploy your Worker:
npx wrangler deploy
View Analytics:
Go to AI > AI Gateway in Cloudflare Dashboard
Select your gateway (my-ai-gateway)
View metrics including:
Request counts and success rates
Response times and latency
Cache hit rates and efficiency
Error rates and types
Token usage and estimated costs
📝 Configure Advanced Features
In the AI Gateway dashboard settings, you can configure:
Rate Limiting:
Set request limits per minute/hour
Configure different limits for different endpoints
Protect against abuse and control costs
Caching Settings:
Adjust cache TTL for different request types
Configure cache keys and invalidation rules
Monitor cache hit rates
Logging:
Enable detailed request/response logging
Configure log retention periods
Export logs for analysis
💡
Pro Tip: Use different cache TTL values for different types of requests. Static content like translations can be cached longer, while dynamic chat responses might need shorter cache times.
Key Takeaways
Centralized Management: AI Gateway provides unified control over AI requests
Cost Optimization: Caching and smart routing reduce AI usage costs
Monitoring: Comprehensive analytics help optimize performance
Reliability: Fallback patterns and error handling improve robustness
Scalability: Built-in rate limiting and caching handle traffic spikes
✅ Fantastic work! You’ve mastered AI Gateway integration and monitoring. Ready for the final step - deploying to production!
STEP 07
Deploy to Production
Deploy your Worker to production and make it accessible to users.
🎯 Learning Objectives
Deploy Workers to production
Configure custom domains
Understand production deployment best practices
🚀Production Deployment
Deploy your Worker to production to make it accessible to real users worldwide.
Simple Deployment: One command to go live
Custom Domains: Connect your own domain
Global Distribution: Instant worldwide availability
Deploy Your Worker
What we're building
Deploy your Worker to production using Wrangler CLI.
Why this matters
Production deployment makes your Worker available to real users on Cloudflare's global network.
Basic Deployment
# Deploy your Worker to productionnpx wrangler deploy
Verify Deployment
# List your deployed Workersnpx wrangler list# Test your Workerhttp https://my-worker.your-subdomain.workers.dev
✅ Worker deployed to production🌍 Available worldwide instantly!🔗 Accessible via workers.dev subdomain
🎉 Congratulations! You’ve successfully deployed your Worker to production and completed the Cloudflare Workers workshop!
Learning Resources
Essential resources for mastering Cloudflare Workers and building serverless applications.
📖 Workers Documentation
Official Cloudflare Workers documentation with API references and best practices