| name | cf-edge |
| description | Deploy web apps, APIs, static sites, and edge functions to Cloudflare's free tier using wrangler and cloudflared CLIs. Use when user wants to (1) host/deploy a website, blog, or web app, (2) create serverless APIs or edge functions, (3) set up databases (SQL or KV), (4) store files/objects, (5) expose localhost via tunnel, (6) deploy any personal project to the cloud for free. Covers Workers, Pages, D1, KV, R2, Durable Objects, Workers AI, Tunnels, Email Routing. All deployments stay within $0 free tier limits. |
Cloudflare Free Tier Deployment
Deploy to Cloudflare's edge network at $0 cost. All services have free tiers sufficient for personal projects.
Prerequisites
wrangler --version
cloudflared --version
npm install -g wrangler
brew install cloudflare/cloudflare/cloudflared
Quick Deploy Commands
Static Site (Pages)
wrangler pages project create <name>
wrangler pages deploy ./dist
Serverless API (Workers)
wrangler init <name> && cd <name>
wrangler dev
wrangler deploy
SQL Database (D1)
wrangler d1 create <name>
wrangler d1 execute <name> --command "CREATE TABLE ..."
Key-Value Store (KV)
wrangler kv:namespace create <NAME>
Object Storage (R2) — requires credit card, won't charge under limits
wrangler r2 bucket create <name>
wrangler r2 object put <bucket>/path --file ./file
Expose Localhost (Tunnel)
cloudflared tunnel --url http://localhost:3000
Free Tier Limits (HARD CONSTRAINTS)
| Service | Limit | Reset |
|---|
| Workers | 100K req/day, 10ms CPU/req | Daily UTC |
| Pages | Unlimited bandwidth, 500 builds/mo | Monthly |
| D1 | 5 GB storage, 5M reads/day, 100K writes/day | Daily UTC |
| KV | 1 GB storage, 100K reads/day, 1K writes/day | Daily UTC |
| R2 | 10 GB storage, $0 egress | Monthly |
| Durable Objects | 100K req/day, 5 GB storage | Daily UTC |
| Workers AI | 10K neurons/day (~500 LLM queries) | Daily UTC |
| Tunnels | Unlimited | — |
See references/limits.md for detailed breakdown.
wrangler.toml Template
name = "my-app"
main = "src/index.js"
compatibility_date = "2024-01-01"
[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "<from wrangler d1 create>"
[[kv_namespaces]]
binding = "KV"
id = "<from wrangler kv:namespace create>"
[[r2_buckets]]
binding = "BUCKET"
bucket_name = "my-bucket"
[vars]
ENVIRONMENT = "production"
Worker Patterns
Basic API Router
export default {
async fetch(request, env) {
const url = new URL(request.url);
if (url.pathname === '/api/data') {
const data = await env.DB.prepare('SELECT * FROM items').all();
return Response.json(data.results);
}
return new Response('Not Found', { status: 404 });
}
};
With D1 + KV
export default {
async fetch(request, env) {
const cached = await env.KV.get('key', 'json');
if (cached) return Response.json(cached);
const { results } = await env.DB.prepare('SELECT * FROM users WHERE id = ?').bind(1).all();
await env.KV.put('key', JSON.stringify(results), { expirationTtl: 3600 });
return Response.json(results);
}
};
Workers AI
export default {
async fetch(request, env) {
const response = await env.AI.run('@cf/meta/llama-3.2-1b-instruct', {
prompt: 'Hello, how are you?'
});
return Response.json(response);
}
};
Persistent Tunnel (Custom Domain)
cloudflared tunnel login
cloudflared tunnel create <tunnel-name>
cloudflared tunnel route dns <tunnel-name> subdomain.yourdomain.com
cat << EOF > ~/.cloudflared/config.yml
tunnel: <tunnel-id>
credentials-file: ~/.cloudflared/<tunnel-id>.json
ingress:
- hostname: subdomain.yourdomain.com
service: http://localhost:3000
- service: http_status:404
EOF
cloudflared tunnel run <tunnel-name>
Staying Within Free Limits
- Before deploying: Estimate daily requests — stay under 100K/day for Workers
- Use caching: KV for read-heavy data reduces D1 reads
- Optimize queries: Add indexes to D1, avoid full table scans
- Static over dynamic: Serve static assets from Pages (unlimited) not Workers
- Monitor usage:
wrangler d1 info <db> or check dashboard
What NOT to Do (ToS Violations)
- Don't use CDN primarily for video streaming or large media distribution
- Don't proxy traffic for other sites (reverse proxy abuse)
- Don't run crypto mining or similar compute-heavy workloads
- Don't exceed 10ms CPU per Worker request consistently
Project Structure Recommendations
my-project/
├── wrangler.toml
├── package.json
├── src/
│ └── index.js
├── public/
└── migrations/
└── 0001_init.sql
Common Commands Reference
wrangler dev
wrangler dev --remote
wrangler deploy
wrangler pages deploy ./dist
wrangler d1 execute <db> --file ./migrations/001.sql
wrangler d1 execute <db> --command "SELECT * FROM users"
wrangler tail
wrangler tail --format pretty
wrangler whoami
wrangler d1 info <db>
See Also