The gist
Picture this: you've built a mechanical mail carrier that works great at your house. Now you need to send it off to work on its own, at an office where it shows up every day at 9 a.m. whether you're there or not. Deployment is exactly that: moving your automation from "works on my computer" to "works all the time, in the cloud, without me."
Key concepts
- The difference between running something locally and deploying it to the cloud
- Cloudflare Workers as an edge platform (computing on the servers closest to the user) for 24/7 automations
- Deployments are deterministic: the code runs exactly as written, with no self-correction
- Rate limiting (caps on how often you can make requests) and quotas for API keys (API: application programming interface, the way programs talk to each other) in production
- Vercel for deploying web apps
- Alternatives: Trigger.dev, Modal, Railway (comparison)
Theory
What changes when you deploy
When you're building a workflow with Claude Code, the agent (an autonomous program that carries out tasks) can fix a mistake right in the middle of the work. Wrote the wrong file path? The agent notices, fixes it, and keeps going. This is called adaptive execution.
A deployment doesn't have that. You deploy code and tools, not the agent itself with its ability to reason and correct. The code runs deterministically: step 1 → step 2 → step 3. If something goes wrong at step 2, you get an error. No "hang on, let me rethink this."
Takeaway: all your testing has to happen during development, not in the hope that "production will sort it out."
Cloudflare Workers: your automation factory on the edge
Cloudflare Workers are edge functions that run on Cloudflare's servers in hundreds of cities around the world. They're not a separate SaaS platform (software as a service) but part of Cloudflare's infrastructure.
What Workers can do:
- Cron Triggers (scheduling with cron, a task scheduler): every Monday at 08:00, the first of every month, every 15 minutes
- HTTP webhooks (a webhook is an HTTP notification): a request comes in → the Worker runs its logic
- KV Storage (key-value storage): keep data between runs (state, results, cache)
- Messenger integration: send results straight to a chat bot. The examples below use a Telegram bot; Slack or email work the same way
Why Cloudflare Workers and not Trigger.dev?
| Cloudflare Workers | Trigger.dev | |
|---|---|---|
| Free tier | 100,000 requests/day | There's a free plan; see the pricing page for details |
| Paid | from $5/mo (10 million requests included, then $0.30 per million) | Paid plans; see the pricing page |
| Edge | Hundreds of cities worldwide | Jobs run on the service's servers, not on the edge |
| Storage | KV (built in, with a free allowance) | Needs an external database |
| Monitoring | wrangler tail + logs |
Dashboard (a nice one) |
| GitHub | GitHub Actions or wrangler deploy |
Native integration |
| Execution limit | CPU limit: 10 ms (free); longer limits for cron on paid plans, see the Cloudflare limits page | No limit on duration |
Cloudflare prices and limits in the table are as of October 2026. Current prices and versions: What's current.
When Trigger.dev is better: if a task computes or processes data for longer than the Workers CPU limits allow (heavy scraping, video processing). For most lightweight automations, Workers are cheaper and faster.
Trigger.dev is a good tool. We use Workers because at small scale they cost less and they're built into an ecosystem we already use. Compare using your own numbers.
The deployment process: 5 steps
Step 1: Create a Worker project
npm create cloudflare@latest -- my-automation
cd my-automationThe tool asks a few questions: choose "Hello World example," "Worker only," and TypeScript as the language. It creates a project structure with wrangler.jsonc (the config; in older projects it's wrangler.toml, and the toml format is still supported) and src/index.ts (the code). Below, the config is shown in toml format; the settings mean the same thing either way.
Step 2: Set up secrets
Secrets are added through the CLI (command-line interface), not in files:
wrangler secret put ANTHROPIC_API_KEY
# You type the key in the terminal; it's encrypted and stored in Cloudflare
wrangler secret put TELEGRAM_BOT_TOKENNever store keys in code. Only through wrangler secret put.
Step 3: Set the schedule in wrangler.toml
name = "weekly-job-scraper"
main = "src/index.ts"
compatibility_date = "2026-10-01" # use today's date
[triggers]
crons = ["0 9 * * 1"] # every Monday at 09:00 UTC
[[kv_namespaces]]
binding = "CACHE"
id = "your-kv-namespace-id"Step 4: Write the Worker
export default {
async scheduled(event, env, ctx) {
// 1. Read the previous state from KV
const lastRun = await env.CACHE.get("last-run");
// 2. Call the Anthropic API
const response = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": env.ANTHROPIC_API_KEY,
"content-type": "application/json",
"anthropic-version": "2023-06-01"
},
body: JSON.stringify({
model: "claude-sonnet-5-5", // check the current model ID on the What's current page
max_tokens: 1024,
messages: [{ role: "user", content: "Generate a digest..." }]
})
});
const data = await response.json();
const result = data.content.map((b) => (b.type === "text" ? b.text : "")).join("");
// 3. Send it to Telegram
await fetch(`https://api.telegram.org/bot${env.TELEGRAM_BOT_TOKEN}/sendMessage`, {
method: "POST",
headers: { "content-type": "application/json" },
body: JSON.stringify({
chat_id: env.TELEGRAM_CHAT_ID,
text: result,
parse_mode: "Markdown"
})
});
// 4. Save the state
await env.CACHE.put("last-run", new Date().toISOString());
}
};Step 5: Deploy and monitor
# Deploy
wrangler deploy
# Real-time monitoring
wrangler tail
You test a cron run locally: start npx wrangler dev --test-scheduled, and in another terminal window run:
curl "http://localhost:8787/cdn-cgi/local/scheduled"The Cloudflare Dashboard shows logs for every run, errors and metrics.
A real example: a weekly job listings digest
The task: every Friday, collect job listings and send a digest to a chat bot.
Worker architecture: 1. Cron Trigger: "0 17 * * 5" (Friday 17:00 UTC) 2. Read previous results from KV (for deduplication) 3. Fetch data from 5 job listing APIs 4. Call the Anthropic API to structure + analyze 5. Deduplicate (remove repeats from last week) 6. Save the new results to KV 7. Send the digest to Telegram 8. Record metrics (tokens, the smallest unit of text for AI; cost) in an audit KV
An important limit: CPU time. On the Free tier you get 10 ms of CPU per run; on the Paid plan (from $5/mo) cron jobs get a much longer limit, which depends on how often the job runs (see Cloudflare's limits page). Waiting on the network (API calls, KV reads) doesn't count toward CPU time, so for most API workflows this is enough. For heavy scraping with Playwright, you need Trigger.dev or a separate server.
Rate limiting: the invisible wall
In production you're dealing with real API limits:
Anthropic:
- Limits on requests and tokens per minute depend on your account's tier and on the model; check the exact values in the Claude Console and in the Rate limits section of the documentation
- New accounts start at a low tier, and limits grow as you use the service
If you go over the limit: the API returns a 429 error. Without retry logic, the workflow crashes.
The fix: add delays between requests and use retries with exponential backoff:
async function callWithRetry(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (e) {
if (e.status === 429 && i < maxRetries - 1) {
await new Promise(r => setTimeout(r, 1000 * Math.pow(2, i)));
continue;
}
throw e;
}
}
}Quota planning: if a workflow processes 500 documents a day, figure out how many tokens that will use. Don't go over your daily quotas.
Vercel: for web apps
Cloudflare Workers are for automations and background jobs. Vercel is for web apps and APIs:
- Deploying Next.js / React apps
- Serverless functions (no server to manage): REST API endpoints
- Edge Functions: run close to the user
- Free Hobby plan: fine for personal prototypes, but only for non-commercial projects. Commercial projects need the paid Pro plan ($20 a month per developer, as of October 2026)
A typical setup:
Vercel (web interface) ←→ Cloudflare Workers (background jobs) ←→ KV Storage
↓
Telegram bot (notifications)A user clicks a button on the site → Vercel receives the request → a Cloudflare Worker runs the job → the result goes to KV + a chat notification.
A separate note on static sites: for them and for full-stack apps, Cloudflare now recommends Workers with static files (Workers Static Assets). Pages keeps working, but new features are showing up in Workers (as of October 2026).
Cloudflare Workers: plans
| Setting | Free | Paid (from $5/mo) |
|---|---|---|
| Requests | 100,000/day | no limit (10 million/mo included, then $0.30 per million) |
| CPU time per request | 10 ms | longer; see the limits page |
| KV reads | daily allowance; see the pricing page | monthly allowance included; see the pricing page |
| KV writes | daily allowance; see the pricing page | monthly allowance included; see the pricing page |
| Cron Triggers per account | limited; see the limits page | more; see the limits page |
| Workers | limited; see the limits page | more; see the limits page |
To get started: the Free tier is enough for 1-3 automations. Paid (from $5/mo) is for serious use. Numbers are as of October 2026.
Current prices: Cloudflare Workers Pricing
Comparing deployment platforms
| Platform | What it's for | Price (as of October 2026) | Execution limit | Our pick? |
|---|---|---|---|---|
| Cloudflare Workers | Cron + API automations | from $5/mo, free plan available | CPU: 10 ms (free) / longer for cron (paid) | ✅ Primary |
| Trigger.dev | Heavy, long-running jobs | Free plan and paid plans, see the pricing page | No limit on duration | Alternative |
| Vercel | Web apps + APIs | Hobby free (non-commercial only), Pro $20/mo | Depends on plan, see the docs | For the UI |
| Modal | ML + GPU jobs | Pay-per-use, see the pricing page | See the docs | For AI-heavy work |
| Railway | A full server | See the pricing page | See the docs | If you need a VPS (virtual private server) |
| Render | Web services + cron jobs | See the pricing page | See the docs | Simple deploys |
Common deployment mistakes
Forgetting to set secrets with
wrangler secret put. The most common mistake: you copied the code, deployed it, and the Worker crashes with "undefined" because the API keys aren't set. Always checkwrangler secret listbefore deploying.Not testing locally before deploying.
wrangler devruns the Worker locally, so use it. One run throughwrangler devsaves an hour of debugging in production.Storing secrets in
wrangler.toml. Thewrangler.tomlfile often ends up in git. Secrets (API keys, tokens) go only throughwrangler secret put, never inwrangler.tomlor in code.Ignoring the CPU time limit. Free tier = 10 ms of CPU time. Network waiting doesn't count, but parsing large responses and complex logic can easily blow past it. Use
wrangler tailto check how much CPU time the Worker uses.Forgetting retries on 429 errors. In production, API services return 429 (rate limit) regularly. Without retry logic the Worker will simply crash at 3 a.m., and you'll find out in the morning.
A real wrangler.toml: Worker configuration
name = "my-weekly-digest"
main = "src/index.ts"
compatibility_date = "2026-10-01" # use today's date
# Schedule: every Monday at 09:00 UTC
[triggers]
crons = ["0 9 * * 1"]
# KV storage for state between runs
[[kv_namespaces]]
binding = "CACHE"
id = "abc123def456" # ID from `wrangler kv namespace create CACHE`
preview_id = "xyz789" # for wrangler dev
# Environment variables (NOT secrets, fine to keep in the config)
[vars]
TELEGRAM_CHAT_ID = "123456789"
ENVIRONMENT = "production"
# Secrets are added through the CLI:
# wrangler secret put ANTHROPIC_API_KEY
# wrangler secret put TELEGRAM_BOT_TOKENNote: you get the KV namespace id from wrangler kv namespace create CACHE. Secrets (ANTHROPIC_API_KEY and so on) are set only through wrangler secret put.
Pre-deployment checklist
Before you deploy, be sure to check:
Practice
Exercise: deploy a simple automation to Cloudflare Workers
- Install Node.js (you need it for the commands below). Wrangler comes with the project, so you don't have to install it globally: use
npx wrangler ... - Create a project:
npm create cloudflare@latest -- quote-bot(Hello World, Worker only, TypeScript) - Log in:
npx wrangler login - Write a Worker: every 5 minutes, fetch a record from a public test API (for example jsonplaceholder.typicode.com) and log the result
- Set the cron in the Wrangler config:
crons = ["*/5 * * * *"] - Test locally:
wrangler dev --test-scheduled - Deploy:
wrangler deploy - Watch it run:
wrangler tail - Bonus: add a secret (
wrangler secret put MY_SECRET) and use it in the Worker asenv.MY_SECRET - Bonus 2: create a KV namespace and save the number of the last record so you don't repeat yourself
Expected result: wrangler tail shows regular successful runs with logs of the records.
Tools and resources
- Cloudflare Workers: edge platform for automations
- Wrangler CLI: the CLI for creating, testing and deploying Workers
- Cloudflare KV: key-value storage for state between runs
- Cloudflare D1: an SQL database (SQLite) for Workers, if KV isn't enough
- Cloudflare R2: file storage (similar to S3), with a free allowance (terms on the pricing page)
- Cloudflare Workers Pricing: current plans
- Vercel: deploying web apps; the free Hobby plan is for non-commercial projects only
- Trigger.dev: an alternative for long-running jobs
- Railway: a full server, if you need a VPS
- Render: simple deploys of web services + cron jobs
- GitHub Actions: an alternative for CI/CD (continuous integration and delivery) pipelines
Key takeaways
When you deploy, you're sending code, not the agent. Code doesn't fix itself, so test DURING development, not after.
Rate limiting is a real problem in production. Add delays and retry logic before something crashes at 3 a.m.
Cloudflare Workers = edge speed + KV storage + cron out of the box. At small scale they're noticeably cheaper than Trigger.dev. For most lightweight jobs, they're a good choice.
Related lessons
- → Loop vs Scheduled Tasks: scheduling Worker runs with cron and Trigger.dev
- → Headless Mode and CI/CD: deploying Workers automatically with GitHub Actions
- ← APIs and integrations: Workers make API calls to outside services, so understanding APIs is a must
Next lesson
→ Multimodality: images, PDFs and audio in Claude's work
The mark stays in this browser only and is never sent anywhere. My progress