# Cloudflare KV: a key-value store for your Workers

> Learn how to use Cloudflare Workers KV, an edge key-value store, to create a namespace and put and get data, ideal for sessions, feature flags and caching.

Author: Flavio Copes | Published: 2026-06-24 | Canonical: https://flaviocopes.com/cloudflare-kv/

Sometimes you don't need a full database. You just need to save a value under a key and read it back, fast.

That's **Workers KV**. Think of it as a giant dictionary that lives on Cloudflare's edge. You store a value under a key, and you can read it from anywhere in the world, very quickly.

I use it for sessions, feature flags, and caching things that are expensive to compute. Let's see how it works.

If you're not sure whether KV is the right fit versus D1, R2 or Durable Objects, I built a free [Cloudflare storage chooser](https://flaviocopes.com/tools/cloudflare-storage-chooser/) that points you to the right one.

## Create a namespace

In KV, your keys live in a **namespace**. Create one:

```bash
npx wrangler kv namespace create SESSIONS
```

It prints an id. Add it to `wrangler.jsonc`:

```jsonc
{
  "kv_namespaces": [
    {
      "binding": "SESSIONS",
      "id": "the-id-it-printed"
    }
  ]
}
```

Now `env.SESSIONS` is available in your Worker.

## Write and read

Writing is `put`, reading is `get`:

```js
await env.SESSIONS.put('user-123', 'logged-in')

const status = await env.SESSIONS.get('user-123')
```

`get` returns the value, or `null` if the key isn't there.

## Storing objects

Values are strings, but KV can handle [JSON](https://flaviocopes.com/json/) for you. Pass an object and tell `get` to parse it back:

```js
await env.SESSIONS.put('user-123', JSON.stringify({ name: 'Flavio', plan: 'pro' }))

const user = await env.SESSIONS.get('user-123', 'json')
```

With `'json'`, `get` returns the parsed object directly. No manual `JSON.parse`.

## Expiring keys

This is one of my favorite features. You can tell a key to delete itself after some time. Great for sessions and caches.

Expire after one hour:

```js
await env.SESSIONS.put('user-123', 'logged-in', { expirationTtl: 3600 })
```

`expirationTtl` is in seconds. After it passes, the key is gone. No cleanup job to write.

## Delete a key

```js
await env.SESSIONS.delete('user-123')
```

## List keys

You can list keys, optionally by prefix:

```js
const list = await env.SESSIONS.list({ prefix: 'user-' })
list.keys.forEach((k) => console.log(k.name))
```

This is handy for grouping related keys, like `user-123`, `user-456`.

## The one thing to know

KV is built for reads. Reading is extremely fast, everywhere. Writing is fast too, but a change can take a few seconds to be visible in every region.

So KV is perfect when you read a lot and write occasionally: sessions, config, cached pages, flags.

It's not the tool for data that changes constantly and must be exact the instant after you write it, like a bank balance. For that, reach for D1 or a Durable Object.

But for "save this and read it back fast," KV is the simplest thing on the platform. The full reference is in the [KV docs](https://developers.cloudflare.com/kv/).
