KV Store
Fast key-value storage for simple data lookups.
Overview
KV Store provides a simple key-value interface for storing and retrieving data. Built on Cloudflare KV, it's optimized for fast reads and global distribution.
When to Use KV
Good for:
- User preferences and settings
- Session data and tokens
- Cache and temporary data
- Rate limiting counters
- Feature flags
- Simple lookups by key
Not ideal for:
- Complex queries (use Tables instead)
- Relational data
- Large data sets requiring search
Namespaces
Data is organized into namespaces. Think of a namespace as a bucket for related keys.
Create Namespace
lux data kv init user-preferences "User preference storage"List Namespaces
lux data kv listKey-Value Operations
Set Value
lux data kv set kv_123 "user:456" '{"theme":"dark","language":"en"}'Get Value
lux data kv get kv_123 "user:456"Output:
{
"theme": "dark",
"language": "en"
}Delete Key
lux data kv delete-key kv_123 "user:456"List Keys
lux data kv keys kv_123Key Naming Conventions
Use prefixes to organize keys:
user:{userId} # User data
session:{sessionId} # Session tokens
ratelimit:{userId}:{action} # Rate limiting
feature:{featureName} # Feature flags
cache:{resourceType}:{id} # Cached dataExamples:
user:cust_abc123
session:sess_xyz789
ratelimit:cust_abc123:api_calls
feature:new_checkout
cache:product:prod_123Using KV in Flows
Get Value
Use a Code node or custom KV node:
// Access KV value
const preferences = await kv.get(`user:${inputs.userId}`);
return { preferences: JSON.parse(preferences) };Set Value
// Store KV value
await kv.set(`user:${inputs.userId}`, JSON.stringify({
theme: inputs.theme,
language: inputs.language
}));
return { success: true };Bulk Operations
Set Multiple
lux data kv set-bulk kv_123 '[
{"key": "user:1", "value": "{\"name\":\"Alice\"}"},
{"key": "user:2", "value": "{\"name\":\"Bob\"}"}
]'Delete Multiple
lux data kv delete-bulk kv_123 '["user:1", "user:2"]'Import/Export
Export to JSON
lux data kv export kv_123 ./backup.jsonImport from JSON
lux data kv import kv_123 ./backup.jsonJSON format:
{
"user:1": {"name": "Alice", "theme": "dark"},
"user:2": {"name": "Bob", "theme": "light"}
}Common Patterns
User Preferences
// Get with default
const key = `prefs:${userId}`;
const prefs = await kv.get(key) || '{"theme":"light","notifications":true}';
return JSON.parse(prefs);Rate Limiting
const key = `ratelimit:${userId}:${action}`;
const count = parseInt(await kv.get(key) || '0');
if (count >= 100) {
throw new Error('Rate limit exceeded');
}
await kv.set(key, String(count + 1));
// Note: In production, also set TTL to reset after time windowFeature Flags
const enabled = await kv.get(`feature:${featureName}`);
return { enabled: enabled === 'true' };Caching
const cacheKey = `cache:product:${productId}`;
let product = await kv.get(cacheKey);
if (!product) {
// Fetch from database
product = await fetchFromDB(productId);
await kv.set(cacheKey, JSON.stringify(product));
}
return JSON.parse(product);Performance Notes
- Reads are fast - Globally distributed, low latency
- Writes are eventually consistent - May take seconds to propagate
- Keys are limited - Max 512 bytes per key
- Values are limited - Max 25 MB per value (keep smaller for performance)
Best Practices
- Use descriptive key prefixes - Makes debugging easier
- Store JSON - Serialize complex objects
- Keep values small - Faster reads
- Use TTL for temporary data - Auto-cleanup
- Consider consistency - Writes may take time to propagate
See Also: