Building with Edge KV: from feature flags to cart state

Edge KV is globally replicated key-value storage: written at one edge location, readable everywhere. It's fast — 1ms P99 reads at the 90th percentile of locations — and it powers most of what makes our platform feel instant. Here are the three patterns we see work best in production, and the mistakes we made while learning them.

Pattern 1: feature flags

Flags are the simplest fit. A key per flag, a JSON value with rollout percentage, and the Worker evaluates it on every request. Because reads are cheap and replicated, flag evaluation adds negligible latency at the edge.

export default {
  async fetch(request, env) {
    const flags = await env.FLAGS.get("billing-v2", "json");
    if (flags.enabled && Math.random() * 100 < flags.rolloutPct) {
      return await handleBillingV2(request, env);
    }
    return await handleBillingV1(request, env);
  },
};

Pattern 2: cache and session-ish state

For non-critical state — shopping cart contents, draft form data, rate-limit counters — KV is a natural home. Use a short TTL and design for occasional loss; KV is not a database, and treating it like one is how teams get burned.

await env.CARTS.put(`cart:${userId}`, JSON.stringify(cart), {
  expirationTtl: 86400,   // 24h — carts are disposable
});

Two rules make this safe: keep values small (KB scale, not MB), and never put your source of truth exclusively in KV without a durable fallback.

Pattern 3: global configuration

Config that must be identical everywhere — routing tables, feature definitions, API keys for external services — lives perfectly in KV. Writes propagate fast, and Workers always read from the nearest replica.

Consistency model, honestly

KV is eventually consistent. A write is visible near-instantly in the region that accepted it, and propagates worldwide within seconds. For cart state and flags, that's fine. For money and ordering, it's not — use a strongly-consistent store for those, and keep KV for the long tail.

Our guidance in one sentence: KV for config, flags, and disposable state; durable storage for anything you can't afford to lose.

Mistakes we made early

We once stored large payloads (hundreds of KB) per key and watched read P99 climb. We also built a feature that wrote on every request, which multiplied write amplification across 280 locations. Both were fixable by going back to first principles: small values, batched writes, TTL on everything that doesn't need to live forever.

The CLI reference covers the KV commands, and the API reference documents bindings and limits in full.