Skip to main content
Access Cloudflare storage primitives for simple data persistence.
For SQL databases and structured queries, see the data operation.

Configuration

config:
  type: string       # kv, r2, cache
  action: string     # get, put, delete, list
  [type-specific options]

KV (Key-Value Store)

Global key-value cache with eventual consistency. Perfect for configuration, sessions, and caching.

GET Operation

operations:
  - name: get-user
    operation: storage
    config:
      type: kv
      action: get
      key: user-${input.id}
Output:
{
  value: any | null     // Parsed JSON value
  found: boolean        // true if key exists
  metadata: object      // Optional metadata
}

PUT Operation

operations:
  - name: cache-user
    operation: storage
    config:
      type: kv
      action: put
      key: user-${input.id}
      value: ${input.data}
      expirationTtl: 3600  # Expires in 1 hour
Options:
  • expirationTtl (number) - Seconds until expiration
  • expiration (number) - Unix timestamp for expiration
  • metadata (object) - Custom metadata (max 1KB)

DELETE Operation

operations:
  - name: invalidate-cache
    operation: storage
    config:
      type: kv
      action: delete
      key: user-${input.id}

LIST Operation

operations:
  - name: list-users
    operation: storage
    config:
      type: kv
      action: list
      prefix: user-
      limit: 100
Options:
  • prefix (string) - Filter keys by prefix
  • limit (number) - Max results (default: 1000, max: 1000)
  • cursor (string) - Pagination cursor
Output:
{
  keys: Array<{
    name: string
    expiration?: number
    metadata?: object
  }>
  list_complete: boolean
  cursor?: string
}

R2 (Object Storage)

S3-compatible object storage for files, images, backups, and large data.

GET Object

operations:
  - name: get-file
    operation: storage
    config:
      type: r2
      action: get
      key: documents/${input.filename}
Output:
{
  body: ReadableStream | string | ArrayBuffer
  httpMetadata: {
    contentType?: string
    contentLanguage?: string
    contentDisposition?: string
    contentEncoding?: string
    cacheControl?: string
    cacheExpiry?: Date
  }
  customMetadata: Record<string, string>
  size: number
  etag: string
  uploaded: Date
}

PUT Object

operations:
  - name: upload-file
    operation: storage
    config:
      type: r2
      action: put
      key: documents/${input.filename}
      value: ${input.content}
      httpMetadata:
        contentType: ${input.contentType}
      customMetadata:
        uploadedBy: ${input.userId}
        category: ${input.category}
Options:
  • httpMetadata (object) - Standard HTTP metadata
  • customMetadata (object) - Custom key-value metadata (max 2KB)

DELETE Object

operations:
  - name: delete-file
    operation: storage
    config:
      type: r2
      action: delete
      key: documents/${input.filename}

LIST Objects

operations:
  - name: list-files
    operation: storage
    config:
      type: r2
      action: list
      prefix: documents/
      limit: 1000
Options:
  • prefix (string) - Filter by prefix
  • limit (number) - Max results (default: 1000)
  • delimiter (string) - Directory delimiter
  • cursor (string) - Pagination cursor
  • include (string[]) - Include metadata: ['httpMetadata', 'customMetadata']
Output:
{
  objects: Array<{
    key: string
    size: number
    etag: string
    uploaded: Date
    httpMetadata?: object
    customMetadata?: object
  }>
  truncated: boolean
  cursor?: string
  delimitedPrefixes: string[]
}

HEAD Object (Metadata Only)

operations:
  - name: check-file
    operation: storage
    config:
      type: r2
      action: head
      key: documents/${input.filename}
Returns object metadata without downloading the body.

Cache API

Edge cache for ultra-fast data access across Cloudflare’s global network.

GET Operation

operations:
  - name: get-cached-data
    operation: storage
    config:
      type: cache
      action: get
      key: api-response-${input.id}

PUT Operation

operations:
  - name: cache-api-response
    operation: storage
    config:
      type: cache
      action: put
      key: api-response-${input.id}
      value: ${previous.api-call.data}
      ttl: 3600  # 1 hour
Options:
  • ttl (number) - Seconds until expiration
  • cacheControl (string) - Custom Cache-Control header

DELETE Operation

operations:
  - name: invalidate-cache
    operation: storage
    config:
      type: cache
      action: delete
      key: api-response-${input.id}

Choosing Between Storage Types

TypeUse CaseDurabilitySpeedGlobal
KVConfig, sessions, cacheHigh (replicated)Fast (<1ms local)✅ Yes
R2Files, images, backupsVery High (S3-compatible)Medium (10-50ms)✅ Yes
CacheTemporary data, API responsesNone (can evict)Very Fast (<1ms)✅ Yes

When to Use storage vs data

Use storage when you need:
  • ✅ Simple key-value lookups
  • ✅ Object/file storage
  • ✅ Temporary caching
  • ✅ Global edge caching
Use data when you need:
  • ❌ SQL queries
  • ❌ Relational data
  • ❌ Transactions
  • ❌ Complex queries with JOINs
See data operation for database queries.

Examples

Session Management with KV and Cookies

Combine KV storage with the cookies operation for complete session management:
agents:
  # Read session ID from cookie
  - name: get-session
    condition: ${input.cookies.session_id}
    operation: storage
    config:
      type: kv
      action: get
      key: session-${input.cookies.session_id}

  # Create new session if none exists
  - name: create-session
    condition: ${!input.cookies.session_id}
    operation: code
    config:
      handler: |
        const id = crypto.randomUUID()
        return { sessionId: id, data: { created: Date.now() } }

  # Store new session in KV
  - name: save-session
    condition: ${!input.cookies.session_id}
    operation: storage
    config:
      type: kv
      action: put
      key: session-${create-session.output.sessionId}
      value: ${create-session.output.data}
      expirationTtl: 86400  # 24 hours

  # Set session cookie
  - name: set-session-cookie
    condition: ${!input.cookies.session_id}
    operation: cookies
    config:
      action: set
      name: session_id
      value: ${create-session.output.sessionId}
      httpOnly: true
      secure: true
      sameSite: lax
      maxAge: 86400
      purpose: essential

output:
  session: ${get-session.output.value || create-session.output.data}

File Upload to R2

operations:
  - name: upload-file
    operation: storage
    config:
      type: r2
      action: put
      key: uploads/${input.userId}/${input.filename}
      value: ${input.fileData}
      contentType: ${input.mimeType}

API Response Caching

operations:
  # Try cache first
  - name: check-cache
    operation: storage
    config:
      type: cache
      action: get
      key: api-${input.endpoint}

  # Call API if cache miss
  - name: call-api
    operation: http
    when: ${previous.check-cache.found === false}
    config:
      url: https://api.example.com/${input.endpoint}

  # Cache the response
  - name: cache-response
    operation: storage
    when: ${previous.call-api.success}
    config:
      type: cache
      action: put
      key: api-${input.endpoint}
      value: ${previous.call-api.data}
      ttl: 300  # 5 minutes

Bindings Setup

Configure storage bindings in wrangler.toml:
# KV binding
[[kv_namespaces]]
binding = "CACHE"
id = "your-kv-id"

# R2 binding
[[r2_buckets]]
binding = "STORAGE"
bucket_name = "my-bucket"

Performance Tips

KV Best Practices

  • Keep values under 25MB (max limit)
  • Use expiration to auto-cleanup
  • Leverage eventual consistency model
  • Cache frequently accessed keys

R2 Best Practices

  • Use multipart upload for files >100MB
  • Set appropriate content types
  • Use prefixes for organization
  • Leverage custom metadata for search

Cache Best Practices

  • Set reasonable TTLs
  • Invalidate on writes
  • Use cache keys carefully
  • Monitor cache hit rates

Storage Limits

StorageMax Value SizeMax KeysOperations
KV25 MBUnlimited1000 write/sec
R25 TB per objectUnlimitedUnlimited
CacheVaries by planN/AUnlimited
  • data - SQL queries and database operations
  • http - HTTP requests
  • queue - Message queues