← Changelog

Edge Architecture — Astro 5 on Cloudflare Workers

Foundation 2026-06-25

Chose Astro 5 SSR with the Cloudflare Workers adapter as the runtime — no origin server, every request processed at the edge, static pages prerendered at deploy and dynamic routes served by Workers.

Why Astro 5

I evaluated Next.js, SvelteKit, Remix, and static-only generators before settling on Astro. The deciding factor was the islands architecture: zero JavaScript ships by default, and you opt into client-side JS only where it’s genuinely needed. For a personal site where most pages are read-only content, this matters. The runtime footprint starts at nothing rather than starting heavy and hoping tree-shaking does its job.

Astro 5 added content layer improvements and a cleaner SSR story. The Cloudflare adapter (@astrojs/cloudflare) is first-party and well-maintained.

Why Cloudflare Workers (not Vercel, not Netlify)

The real reason is the data layer. I wanted to run bot classification middleware before the page handler runs — no round-trip to an origin, no cold start waiting on a Lambda. Cloudflare Workers run in V8 isolates with sub-millisecond startup time. KV reads are co-located with the edge node, typically under 1ms. D1 (SQLite at the edge) adds ~10ms for writes.

That combination means: every HTTP request can be logged to D1, classified, and have its data written to KV for dashboard reads — all without adding perceptible latency to the page response.

What I gave up: The Cloudflare adapter is stricter than Node. Some npm packages that depend on Node built-ins (fs, crypto, stream) don’t run at the edge. This forced me to use edge-compatible alternatives or vendor small utilities. The constraint is real but manageable.

Request flow

  1. Browser sends request to leedriggers.com
  2. DNS resolves to Cloudflare’s network → nearest edge node
  3. Worker middleware intercepts: extracts UA, path, country, ASN, cf-verified-bot header
  4. Log entry written to D1 (crawl_log table) — async, doesn’t block response
  5. Request routed to Astro handler:
    • Static pages: served from prerendered HTML in Workers Assets
    • Dynamic routes (/crawl-stats/, /api/*): Astro SSR handler runs
  6. Response returned from edge — no origin server involved

Tradeoffs in practice

DecisionBenefitCost
Astro islandsZero JS by defaultExtra config when you do need client JS
Cloudflare WorkersSub-ms KV reads, co-located D1No Node built-ins; adapter constraints
SSR at edgeDynamic routes, real-time dataBuild pipeline more complex than pure static
Prerender static pagesFast TTFB for contentMust be deterministic at build time
← All entries