Skip to main content

Overview

Workers KV is a global, low-latency key-value data store. It supports exceptionally high read volumes with low latency, making it ideal for storing configuration data, cached content, and user preferences.

Managing Namespaces

Create a Namespace

Create a new KV namespace with an optional preview namespace for development:
wrangler kv namespace create <namespace> [--preview]
Options:
  • <namespace> - The name of the new namespace
  • --preview - Create a preview namespace for testing
  • --env <environment> - Target a specific environment
  • --update-config - Automatically add the namespace to your wrangler.json
  • --name <binding-name> - Custom binding name for the namespace
Example:
# Create a production namespace
wrangler kv namespace create my-cache

# Create a preview namespace
wrangler kv namespace create my-cache --preview
After creation, add the namespace to your configuration:
wrangler.json
{
  "kv_namespaces": [
    {
      "binding": "MY_CACHE",
      "id": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
    }
  ]
}

List Namespaces

View all KV namespaces in your account:
wrangler kv namespace list
Outputs JSON with namespace details including IDs and titles.

Rename a Namespace

Rename an existing KV namespace:
wrangler kv namespace rename <old-name> --new-name <new-name>
Options:
  • <old-name> - Current namespace name (positional)
  • --namespace-id <id> - Target by ID instead of name
  • --new-name <name> - New namespace name (required)
Example:
wrangler kv namespace rename old-cache --new-name new-cache

Delete a Namespace

Delete a namespace and all its data:
wrangler kv namespace delete <namespace>
Options:
  • <namespace> - Namespace name to delete
  • --binding <name> - Target by binding name
  • --namespace-id <id> - Target by namespace ID
  • --preview - Delete a preview namespace
  • -y, --skip-confirmation - Skip the confirmation prompt
This action is irreversible and permanently deletes all data in the namespace.

Key-Value Operations

Write a Key-Value Pair

Store a value in a KV namespace:
wrangler kv key put <key> <value> --binding <binding>
Options:
  • <key> - The key to write to
  • <value> - The value to write (mutually exclusive with --path)
  • --path <file> - Read value from a file
  • --binding <name> - Binding name from your config
  • --namespace-id <id> - Namespace ID to use
  • --preview - Write to preview namespace
  • --ttl <seconds> - Time-to-live in seconds
  • --expiration <timestamp> - UNIX timestamp for expiration
  • --metadata <json> - Arbitrary JSON metadata
  • --local - Use local storage (for dev)
  • --persist-to <dir> - Directory for local persistence
Examples:
# Write a simple value
wrangler kv key put "config:theme" "dark" --binding MY_CACHE

# Write from a file
wrangler kv key put "html:home" --path ./index.html --binding MY_CACHE

# Write with expiration (24 hours)
wrangler kv key put "session:abc" "user-data" --binding MY_CACHE --ttl 86400

# Write with metadata
wrangler kv key put "user:123" "data" --binding MY_CACHE --metadata '{"version":"1.0"}'

Bulk Operations

Bulk Put

Upload multiple key-value pairs from a JSON file:
wrangler kv bulk put <filename> --binding <binding>
JSON Format:
[
  {
    "key": "config:theme",
    "value": "dark",
    "expiration_ttl": 86400,
    "metadata": {"version": "2.0"}
  },
  {
    "key": "config:lang",
    "value": "en",
    "base64": false
  }
]
Fields:
  • key - Key name (required)
  • value - Value to store (required)
  • expiration - UNIX timestamp for expiration
  • expiration_ttl - Seconds until expiration
  • metadata - JSON object for metadata
  • base64 - Whether value is base64 encoded

Bulk Get

Retrieve multiple values by keys (Open Beta):
wrangler kv bulk get <filename> --binding <binding>
Input Format:
["key1", "key2", "key3"]
Or with objects:
[{"name": "key1"}, {"name": "key2"}]

Bulk Delete

Delete multiple keys from a namespace:
wrangler kv bulk delete <filename> --binding <binding>
Options:
  • -f, --force - Skip confirmation prompt
Input Format:
["key1", "key2", "key3"]

Local Development

Using Local Storage

Test KV operations locally without affecting production data:
# Write to local storage
wrangler kv key put "test" "value" --binding MY_CACHE --local

# Read from local storage
wrangler kv key get "test" --binding MY_CACHE --local

# Specify persistence directory
wrangler kv key put "test" "value" --binding MY_CACHE --local --persist-to ./.wrangler
Local mode stores data in .wrangler/state/v3/kv/ by default.

Worker Integration

Access KV from your Worker code:
export default {
  async fetch(request, env) {
    // Get a value
    const theme = await env.MY_CACHE.get("config:theme");
    
    // Get with metadata
    const { value, metadata } = await env.MY_CACHE.getWithMetadata("user:123");
    
    // Put a value
    await env.MY_CACHE.put("session:abc", "data", {
      expirationTtl: 3600,
      metadata: { userId: "123" }
    });
    
    // Delete a value
    await env.MY_CACHE.delete("session:old");
    
    // List keys
    const { keys } = await env.MY_CACHE.list({ prefix: "user:" });
    
    return new Response("OK");
  }
};

Best Practices

Key Naming

  • Use prefixes for organization: user:123, config:theme
  • Keep keys under 512 bytes
  • Use consistent naming conventions
  • Avoid special characters when possible

Value Limits

  • Maximum value size: 25 MiB
  • Maximum metadata size: 1 KiB
  • Use expiration for temporary data
  • Consider compression for large values

Performance

  • KV is optimized for high read volumes
  • Writes propagate globally (eventual consistency)
  • Use list() pagination for large datasets
  • Cache frequently accessed data

Development

  • Use preview namespaces for testing
  • Test with --local flag during development
  • Use --persist-to for consistent local state
  • Version your data with metadata

Error Handling

Common errors and solutions:
Ensure the namespace exists and you’re using the correct binding name or namespace ID:
wrangler kv namespace list
The specified key doesn’t exist in the namespace. Check the key name and use kv key list to verify.
Metadata must be valid JSON. Use proper escaping:
--metadata '{"version":"1.0","author":"user"}'
Values must be under 25 MiB. Consider:
  • Compressing the data
  • Splitting into multiple keys
  • Using R2 for larger objects

Build docs developers (and LLMs) love