KV Stores
What are KV Stores?
Section titled “What are KV Stores?”KV (Key-Value) stores hold the metadata about your uploads - things like file names, sizes, upload progress, and processing status. While Data Stores hold the actual file content, KV stores hold the information about those files.
Think of it like a library catalog: the books are stored on shelves (data stores), but the catalog (KV store) tells you which book is where, who checked it out, and when it’s due back.
When to Use Each Store
Section titled “When to Use Each Store”| Store | Best For | Not Recommended For |
|---|---|---|
| Memory | Development, testing, single-process apps | Production, multi-server |
| Redis | Production apps, multi-server deployments | Serverless/edge functions |
| IORedis | Redis clusters, enterprise setups | Simple deployments |
| Cloudflare KV | Edge deployments, global distribution | Strong consistency needs |
| Cloudflare DO | Edge with strong consistency | Non-Cloudflare environments |
| Filesystem | Local development, persistence without Redis | Multi-server production |
Quick Decision Guide:
- Local development? Use Memory (simplest) or Filesystem (persists between restarts)
- Single production server? Use Redis
- Multiple servers? Use Redis (shared state)
- Cloudflare Workers? Use Cloudflare KV or Durable Objects
- Need strong consistency at the edge? Use Cloudflare Durable Objects
Quick Start
Section titled “Quick Start”import { memoryKvStore } from "@uploadista/kv-store-memory";
// Use directly - no configuration neededconst kvStore = memoryKvStore;Data is lost when the process restarts. Perfect for development.
import { redisKvStore } from "@uploadista/kv-store-redis";import { createClient } from "@redis/client";
const redis = createClient({ url: process.env.REDIS_URL || "redis://localhost:6379",});await redis.connect();
const kvStore = redisKvStore({ redis });Required environment variable:
REDIS_URL=redis://localhost:6379import { cloudflareKvStore } from "@uploadista/kv-store-cloudflare-kv";
// In your Cloudflare Workerexport default { async fetch(request, env) { const kvStore = cloudflareKvStore({ kv: env.UPLOADISTA_KV }); // ... },};Required wrangler.toml binding:
[[kv_namespaces]]binding = "UPLOADISTA_KV"id = "your-kv-namespace-id"import { fileKvStore } from "@uploadista/kv-store-filesystem";
const kvStore = fileKvStore({ directory: "./data/kv-store",});Data persists to disk. Good for local development when you want data to survive restarts.
Available KV Stores
Section titled “Available KV Stores”Memory Store
Section titled “Memory Store”The simplest option - stores everything in memory. Zero configuration required.
Installation:
npm install @uploadista/kv-store-memorypnpm add @uploadista/kv-store-memoryyarn add @uploadista/kv-store-memoryCharacteristics:
- Ultra-fast (nanoseconds)
- No external dependencies
- Data lost on restart
- Single process only
Best for: Development, testing, prototyping
Redis Store
Section titled “Redis Store”Production-ready distributed storage using Redis. Supports sharing state across multiple server instances.
Installation:
npm install @uploadista/kv-store-redis @redis/clientpnpm add @uploadista/kv-store-redis @redis/clientyarn add @uploadista/kv-store-redis @redis/clientConfiguration:
import { redisKvStore } from "@uploadista/kv-store-redis";import { createClient } from "@redis/client";
// Basic connectionconst redis = createClient({ url: "redis://localhost:6379",});
// With authenticationconst redis = createClient({ url: "redis://localhost:6379", password: process.env.REDIS_PASSWORD,});
// With TLS (for cloud Redis)const redis = createClient({ url: "rediss://your-redis-host:6380", password: process.env.REDIS_PASSWORD,});
await redis.connect();const kvStore = redisKvStore({ redis });Characteristics:
- Sub-millisecond latency
- Shared across multiple servers
- Optional persistence (RDB/AOF)
- Supports clustering for high availability
Best for: Production deployments, multi-server setups
IORedis Store
Section titled “IORedis Store”Alternative Redis client with built-in cluster and sentinel support. Use this if you need advanced Redis features.
Installation:
npm install @uploadista/kv-store-ioredis ioredispnpm add @uploadista/kv-store-ioredis ioredisyarn add @uploadista/kv-store-ioredis ioredisBasic configuration:
import { ioredisKvStore } from "@uploadista/kv-store-ioredis";import Redis from "ioredis";
const redis = new Redis({ host: "localhost", port: 6379, password: process.env.REDIS_PASSWORD,});
const kvStore = ioredisKvStore({ redis });Cluster configuration:
import Redis from "ioredis";
const cluster = new Redis.Cluster([ { host: "node1", port: 6379 }, { host: "node2", port: 6379 }, { host: "node3", port: 6379 },]);
const kvStore = ioredisKvStore({ redis: cluster });Best for: Redis clusters, Sentinel setups, enterprise deployments
Cloudflare KV Store
Section titled “Cloudflare KV Store”Edge-distributed key-value storage for Cloudflare Workers. Data is replicated globally for fast reads.
Installation:
npm install @uploadista/kv-store-cloudflare-kvpnpm add @uploadista/kv-store-cloudflare-kvyarn add @uploadista/kv-store-cloudflare-kvConfiguration:
import { cloudflareKvStore } from "@uploadista/kv-store-cloudflare-kv";
// Inside your Cloudflare Workerexport default { async fetch(request, env) { const kvStore = cloudflareKvStore({ kv: env.UPLOADISTA_KV }); // Use kvStore with Uploadista },};wrangler.toml:
[[kv_namespaces]]binding = "UPLOADISTA_KV"id = "abc123"Characteristics:
- Global edge distribution
- Fast reads (< 10ms worldwide)
- Eventually consistent (writes take ~60 seconds to propagate)
- Cloudflare Workers only
Best for: Global edge deployments where eventual consistency is acceptable
Cloudflare Durable Objects Store
Section titled “Cloudflare Durable Objects Store”Strongly consistent edge storage with state isolation. Each upload gets its own Durable Object.
Installation:
npm install @uploadista/kv-store-cloudflare-dopnpm add @uploadista/kv-store-cloudflare-doyarn add @uploadista/kv-store-cloudflare-doConfiguration:
import { durableObjectKvStore } from "@uploadista/kv-store-cloudflare-do";
// Inside your Durable Objectexport class UploadDO { constructor(state, env) { this.state = state; }
async fetch(request) { const kvStore = durableObjectKvStore({ storage: this.state.storage }); // Use kvStore with Uploadista }}Characteristics:
- Strong consistency
- Per-object isolation
- Automatic scaling
- Cloudflare Workers only
Best for: Edge deployments requiring strong consistency
Filesystem Store
Section titled “Filesystem Store”File-based storage for local development with persistence. Each key is stored as a file.
Installation:
npm install @uploadista/kv-store-filesystempnpm add @uploadista/kv-store-filesystemyarn add @uploadista/kv-store-filesystemConfiguration:
import { fileKvStore } from "@uploadista/kv-store-filesystem";
const kvStore = fileKvStore({ directory: "./data/kv-store",});Characteristics:
- Data persists between restarts
- No external dependencies
- Slower than memory/Redis
- Single server only
Best for: Local development when you want data to persist
Common Patterns
Section titled “Common Patterns”Development to Production
Section titled “Development to Production”Use different stores for different environments:
import { memoryKvStore } from "@uploadista/kv-store-memory";import { redisKvStore } from "@uploadista/kv-store-redis";import { createClient } from "@redis/client";
let kvStore;
if (process.env.NODE_ENV === "production") { const redis = createClient({ url: process.env.REDIS_URL }); await redis.connect(); kvStore = redisKvStore({ redis });} else { kvStore = memoryKvStore;}Using with Uploadista Server
Section titled “Using with Uploadista Server”KV stores are passed to the Uploadista server during setup:
import { createUploadistaServer } from "@uploadista/server";import { redisKvStore } from "@uploadista/kv-store-redis";import { s3Store } from "@uploadista/data-store-s3";
const uploadista = await createUploadistaServer({ kvStore: redisKvStore({ redis }), dataStore: s3Store({ /* ... */ }), // ... other options});High Availability with Redis Cluster
Section titled “High Availability with Redis Cluster”For production deployments that need high availability:
import Redis from "ioredis";import { ioredisKvStore } from "@uploadista/kv-store-ioredis";
const cluster = new Redis.Cluster([ { host: "redis-1.example.com", port: 6379 }, { host: "redis-2.example.com", port: 6379 }, { host: "redis-3.example.com", port: 6379 },], { redisOptions: { password: process.env.REDIS_PASSWORD, },});
const kvStore = ioredisKvStore({ redis: cluster });Troubleshooting
Section titled “Troubleshooting””Connection refused” with Redis
Section titled “”Connection refused” with Redis”- Verify Redis is running:
redis-cli pingshould returnPONG - Check the hostname and port are correct
- If using Docker, ensure the container is on the same network
Data disappearing on restart
Section titled “Data disappearing on restart”- Memory store: This is expected - use Filesystem or Redis for persistence
- Redis without persistence: Enable RDB or AOF in Redis configuration
- Cloudflare KV: Data should persist - check your namespace binding
Slow reads with Cloudflare KV
Section titled “Slow reads with Cloudflare KV”Cloudflare KV is optimized for read-heavy workloads. If you’re doing many writes:
- Consider Durable Objects for write-heavy scenarios
- Writes can take up to 60 seconds to propagate globally
Redis memory usage growing
Section titled “Redis memory usage growing”- Set a
maxmemorylimit in Redis configuration - Configure an eviction policy (e.g.,
maxmemory-policy allkeys-lru) - Ensure old upload metadata is being cleaned up
Related Concepts
Section titled “Related Concepts”- Data Stores - Where file content is stored
- Upload Engine - Uses KV stores to track uploads
- Uploadista Server - Configure your server
- Event System - Works alongside KV stores for real-time updates