Skip to content

Adr 0003 Worker Splitting And Kv Elimination

Worker Splitting & Astro Session KV Write-Up

Write-Up Scope: The general multi-worker and caching outcomes from this investigation are already captured in MULTI_WORKER_PLATFORM_SERVICES.md, APP_SERVING_CACHE.md, and DATA_STORAGE_PATTERN.md. This write-up is retained specifically to document how @astrojs/cloudflare session KV auto-provisioning works and the architectural trade-offs across session driver options.


1. Context: Why @astrojs/cloudflare Provisions KV by Default

  1. Why KV Is Enabled by Default:
    • Astro includes a built-in Sessions API (Astro.session) that allows server-rendered routes (output: "server" or prerender = false) to persist per-visitor data between HTTP requests without shipping state in client-side JavaScript.
    • Because Cloudflare Workers execute in stateless V8 isolates with no shared local filesystem, @astrojs/cloudflare automatically configures Astro’s underlying unstorage session layer to use Cloudflare Workers KV (cloudflare-kv-binding) bound to a namespace named SESSION.
    • When deploying via modern Wrangler, if a Worker requires a SESSION KV binding that is not yet mapped to an existing namespace ID, Wrangler’s automatic resource provisioning creates a new KV namespace in the Cloudflare account on the fly.
  2. What Astro.session Can Be Used For:
    • Server-managed shopping carts or quote builders across multiple pages.
    • Multi-step form wizards and flash messages across POST-redirect-GET flows.
    • Server-side user or administrator authentication state (e.g., Astro.session.get("user")).
  3. Why Unconfigured Auto-Provisioning Caused Friction in Ephemeral Previews:
    • When a client site enabled output: "server" strictly for stateless Edge SSR content rendering (without using Astro.session), leaving the default session behavior active caused Wrangler to auto-provision a new SESSION KV namespace for every ephemeral PR preview worker (<app>-preview-pr-<N>), leaving orphaned KV namespaces behind when previews were torn down.

2. Evaluation of Astro Session Driver Options & Architectural Implications

Choosing a session configuration in astro.config.mjs carries specific runtime guarantees and limitations on Cloudflare Workers:

Option Mechanism Feasibility & Architectural Implications
session: false Completely disables the Astro.session API (Astro.session is undefined) and suppresses the SESSION KV binding. Feasible & Recommended for Stateless Public Frontends: Best choice when output: "server" is used purely for Edge SSR + HTTP caching and no route calls Astro.session. Limitation: Any route or integration that calls Astro.session.get() / .set() will fail unless it uses its own cookie/database auth.
session: { driver: "memory" }
(or sessionDrivers.memory())
Stores session state in an in-memory JavaScript Map inside the running V8 isolate; suppresses the SESSION KV binding. Not Feasible for Durable Multi-Request Production Sessions: Cloudflare Workers run across many globally distributed V8 isolates that do not share memory and can be recycled at any moment. A visitor’s subsequent request may hit a different isolate and lose all in-memory session state. Only viable for single-process local development/testing or as a no-op shim when an integration expects Astro.session to be defined without relying on cross-request persistence.
session: { driver: "cloudflare-kv-binding" }
(Adapter Default)
Stores session state in a Cloudflare Workers KV namespace (SESSION) replicated across Cloudflare’s edge network. Feasible When Durable Edge Sessions Are Needed (With Explicit Binding): Supports persistent cross-request Astro.session state across isolates. Implications: (1) Must be explicitly bound in wrangler.jsonc (with a shared or lifecycle-managed preview namespace) so PR previews do not auto-create orphaned namespaces; (2) KV is eventually consistent globally (up to ~60s across distant regions, though immediate within the same edge PoP), making it suitable for preferences/carts but less suited for strict atomic state transitions.
Custom Cookie / D1 / Service Binding State
(Outside Astro.session)
Carries state in signed/encrypted HttpOnly cookies (e.g., Cloudflare Access JWTs) or validates session tokens against an app-hosted D1 database table (admin_sessions). Feasible for Strong Consistency & Admin Auth: Provides immediate read-after-write consistency (via D1 primary) or zero-storage edge verification (via signed JWTs) while allowing the Astro Worker to keep session: false and avoid KV namespace management altogether.

3. Summary of Guidance

  1. Stateless Public Sites: If an application does not use Astro.session, set session: false so @astrojs/cloudflare does not inject or auto-provision a SESSION KV namespace.
  2. Avoid driver: "memory" for Real User Sessions: Never rely on session: { driver: "memory" } to persist real visitor or admin state across requests in production Workers, as isolate eviction or routing across isolates will drop the session.
  3. Stateful Session Requirements: If a future client capability genuinely requires Astro.session, either bind an explicitly managed KV namespace (accounting for KV’s eventual consistency and preview lifecycle cleanup) or back session state with D1 / signed cookies.