kvGet/kvPut helpers from the Quick Start and the kvGetWithExpiry/kvPutWithExpiry helpers from Key expiration (KV has no native TTL, so expiry is enforced in your code).
Session Storage with Expiry
Store user sessions at the edge with an application-level expiry:- JavaScript
- Python
- Go
const SESSION_TTL = 86400; // 24 hours
async function handler(request) {
const sessionId = request.headers.get("X-Session-ID");
// Read session (null if missing or expired)
let session = await kvGetWithExpiry(`session/${sessionId}`);
if (!session) {
session = JSON.stringify({ created: Date.now(), views: 0 });
} else {
const data = JSON.parse(session);
data.views++;
session = JSON.stringify(data);
}
// Store with a 24h expiry
await kvPutWithExpiry(`session/${sessionId}`, session, SESSION_TTL);
return new Response(session);
}
import json, time
SESSION_TTL = 86400 # 24 hours
# kv_get_with_expiry / kv_put_with_expiry: see Key expiration
async def handler(request):
session_id = request.headers.get("X-Session-ID")
session = await kv_get_with_expiry(f"session/{session_id}")
if not session:
session = json.dumps({"created": int(time.time()), "views": 0})
else:
data = json.loads(session)
data["views"] += 1
session = json.dumps(data)
await kv_put_with_expiry(f"session/{session_id}", session, SESSION_TTL)
return {"body": session}
const sessionTTL = 86400 // 24 hours
// kvGetWithExpiry / kvPutWithExpiry: see Key expiration
func handler(w http.ResponseWriter, r *http.Request) {
sessionID := r.Header.Get("X-Session-ID")
session, _ := kvGetWithExpiry(fmt.Sprintf("session/%s", sessionID))
var data map[string]interface{}
if session == "" {
data = map[string]interface{}{"created": time.Now().Unix(), "views": 0}
} else {
json.Unmarshal([]byte(session), &data)
data["views"] = data["views"].(float64) + 1
}
updated, _ := json.Marshal(data)
kvPutWithExpiry(fmt.Sprintf("session/%s", sessionID), string(updated), sessionTTL)
w.Header().Set("Content-Type", "application/json")
w.Write(updated)
}
API Response Caching with Expiry
Cache expensive API responses with an application-level expiry:- JavaScript
- Python
- Go
const CACHE_TTL = 300; // 5 minutes
async function handler(request) {
const cacheKey = `cache/api${new URL(request.url).pathname}`;
// Check cache
const cached = await kvGetWithExpiry(cacheKey);
if (cached) {
return new Response(cached, {
headers: { "X-Cache": "HIT" }
});
}
// Fetch from origin
const response = await fetch("https://api.example.com/data");
const data = await response.text();
// Cache with a 5-minute expiry
await kvPutWithExpiry(cacheKey, data, CACHE_TTL);
return new Response(data, {
headers: { "X-Cache": "MISS" }
});
}
CACHE_TTL = 300 # 5 minutes
async def handler(request):
from urllib.parse import urlparse
cache_key = f"cache/api{urlparse(request.url).path}"
cached = await kv_get_with_expiry(cache_key)
if cached:
return {"body": cached, "headers": {"X-Cache": "HIT"}}
async with httpx.AsyncClient() as client:
resp = await client.get("https://api.example.com/data")
data = resp.text
await kv_put_with_expiry(cache_key, data, CACHE_TTL)
return {"body": data, "headers": {"X-Cache": "MISS"}}
const cacheTTL = 300 // 5 minutes
func handler(w http.ResponseWriter, r *http.Request) {
cacheKey := fmt.Sprintf("cache/api%s", r.URL.Path)
cached, _ := kvGetWithExpiry(cacheKey)
if cached != "" {
w.Header().Set("X-Cache", "HIT")
w.Write([]byte(cached))
return
}
resp, _ := http.Get("https://api.example.com/data")
defer resp.Body.Close()
data, _ := io.ReadAll(resp.Body)
kvPutWithExpiry(cacheKey, string(data), cacheTTL)
w.Header().Set("X-Cache", "MISS")
w.Write(data)
}
Feature Flags
Store and retrieve feature flags (no expiry needed):- JavaScript
- Python
- Go
async function handler(request) {
const newUIEnabled = await kvGet("flag/new-ui");
if (newUIEnabled === "true") {
return serveNewUI(request);
}
return serveOldUI(request);
}
async def handler(request):
enabled = await kv_get("flag/new-ui")
if enabled == "true":
return serve_new_ui(request)
return serve_old_ui(request)
func handler(w http.ResponseWriter, r *http.Request) {
enabled, _ := kvGet("flag/new-ui")
if enabled == "true" {
serveNewUI(w, r)
return
}
serveOldUI(w, r)
}