Stack B: Cloudflare Pages, Workers and D1 from zero to deployed
No server to patch, no systemd units, generous free tier, one command to deploy. Pages + Workers + D1 with wrangler, end to end.
Stack B: Cloudflare Pages, Workers, D1
Choose your stack covers when this beats a VPS: you don’t want to think about a server at all, and your traffic fits Cloudflare’s generous free tier. This guide goes from an empty folder to a deployed frontend + API + database.
1. Install wrangler and log in
npm install -g wrangler
wrangler login
This opens a browser to authorize the CLI against your Cloudflare account. No credit card needed to start.
2. Create the D1 database
wrangler d1 create my-app-db
This prints a database_id - copy it. D1 is Cloudflare’s SQLite-compatible database, replicated at the edge.
3. Configure the Worker (API)
Create wrangler.toml at the repo root:
name = "my-app-api"
main = "worker/index.ts"
compatibility_date = "2024-04-03"
[vars]
ENVIRONMENT = "production"
[[d1_databases]]
binding = "DB"
database_name = "my-app-db"
database_id = "PASTE-THE-ID-FROM-STEP-2"
[dev]
port = 8788
Secrets (API keys, OAuth credentials) never go in [vars] - they go through:
wrangler secret put DEEPSEEK_API_KEY
Run the migration to create your tables:
wrangler d1 execute my-app-db --remote --file=./migrations/001_init.sql
Deploy the Worker:
wrangler deploy
4. Configure Pages (frontend)
Create wrangler-pages.toml (or use the Pages dashboard directly):
name = "my-app-web"
compatibility_date = "2024-09-23"
compatibility_flags = ["nodejs_compat_v2"]
[vars]
PUBLIC_WORKER_URL = "https://my-app-api.<your-subdomain>.workers.dev"
[build]
command = "npm ci && npm run build"
Deploy:
wrangler pages deploy dist --project-name=my-app-web
Point your custom domain at the Pages project from the Cloudflare dashboard - TLS is handled automatically, no origin cert to manage (unlike Stack A, see domain, DNS, Cloudflare).
5. Local development
wrangler dev # runs the Worker + local D1 on port 8788
Local D1 is a separate SQLite file under .wrangler/ - it does not touch production data. Run your migrations against it the same way, without --remote.
6. What you get for free, and what you don’t
Free tier covers: 100k Worker requests/day, 5GB D1 storage, unlimited Pages requests, automatic edge scaling, zero servers to patch or reboot.
You give up: shell access (no SSH, no tail -f on a log file - you read logs through wrangler tail or the dashboard), direct SQLite file access (D1 is an HTTP API to SQLite, not a local file), and the mental model of “one machine” - a Worker cold-starts on every edge location it runs from, which changes how you think about caching and state.
7. Debugging a live Worker
wrangler tail my-app-api # stream live logs
There’s no journalctl here - wrangler tail is the closest equivalent, but it only shows what happens after you start it (nothing retroactive).
Verdict
If step 3 (wrangler.toml + secrets + D1 migration) felt more abstract than editing a text file over SSH, that’s the real tradeoff of Stack B: less to operate, less to see. Pick it when you want zero operational surface and your app fits the free tier’s shape. If you’d rather have one box you can poke at directly, stay on Stack A.
New models & deals, once a month
New proprietary and open-source models worth trying, price drops, and the best deals on AI coding plans. No spam.