Skip to main content
KV stores values by string key, with an optional expiry and optional metadata. Use it for sessions, settings, feature flags, tokens, and cached API responses. The Cache API always misses on celld, the Judt runtime, so use KV as your cache.

Strong consistency on celld

On celld, KV is strongly consistent. One owner serves each namespace, so a get call always sees the last put call, from every node. Cloudflare’s guidance about stale reads doesn’t apply. This design has the following consequences:
  • Each namespace has one writer.
  • There is no edge cache. Each read goes to the namespace owner.
  • KV still has no atomic increment and no compare-and-swap. For more information, see When not to use KV.

Configure the binding

To add a namespace, declare it in the wrangler.json file:
wrangler.json
The configuration follows these rules:
  • The binding and id keys are required. An id value has 1 to 63 letters, digits, _, and -, and starts with a letter or a digit. Deploy refuses all other values.
  • Deploy refuses every other key, including preview_id.
  • You don’t provision the namespace. celld creates it on first use.
  • Use a separate namespace for each type of data, for example SESSIONS, FLAGS, and CACHE. Each namespace has its own writer.
Don’t change the id value after data exists. A different id opens an empty namespace, and the data stays under the old id.

Read and write values

The following example writes, reads, and deletes values:
Keep the following behavior in mind:
  • A missing key returns null.
  • The expiration option is a time in epoch seconds. The expirationTtl option is a number of seconds after the write. The minimum expiry is 60 seconds.
  • The cacheTtl option has no effect.

List keys

The list method returns a maximum of 1,000 keys for each page, in byte order. To read every page, follow the cursor:
Because keys sort in byte order, design your key prefixes for the queries that you run, for example user:USER_ID: for all keys of one user.

Limits

The following table lists the limits for KV on celld. A call over a limit throws.

When not to use KV

KV isn’t the right binding for the following needs:
  • Counters and read-modify-write: KV has no increment and no compare-and-swap. Two requests that each run get, add one, and put lose an update. Use a Durable Object or a D1 UPDATE ... SET n = n + 1 statement.
  • Queries across values: use D1.
  • Values in module variables: read a value one time for each request. Don’t keep it in a module variable across requests.
  • Large files: use R2.

Cache API responses in KV

The following helper returns a cached value, or computes and stores it with an expiry:
The helper raises the expiry to at least 60 seconds, the KV minimum.

Differences from Cloudflare

celld differs from Cloudflare KV in the following ways:
  • KV is strongly consistent. A read always sees the last write.
  • There is no edge cache, and the cacheTtl option has no effect.
  • Each namespace has one writer.
  • Deploy refuses keys other than binding and id, including preview_id.
  • The Cache API (caches.default and caches.open) always misses, so KV is the cache.