How to Configure Storage for LunaTV: Kvrocks, Redis, and Upstash Setup Guide
LunaTV uses a pluggable storage architecture controlled by the NEXT_PUBLIC_STORAGE_TYPE environment variable, supporting Kvrocks, Redis, Upstash, and local development backends without requiring code changes.
Configuring persistent storage for LunaTV is essential for production deployments. The MoonTechLab/LunaTV repository implements a factory-based storage layer that allows you to switch between Redis-compatible backends—Kvrocks, Upstash, or standard Redis—by adjusting environment variables. This guide explains how to configure storage for LunaTV using the actual source implementation and runtime selection logic found in the codebase.
Supported Storage Backends for LunaTV
LunaTV provides four storage implementations to accommodate different deployment scenarios. The system stores user data—including play records, favorites, and search history—in a key-value store selected at runtime.
Local Storage (Development)
Local storage is an in-memory store intended for development environments. It requires no environment variables and provides zero-configuration testing. However, data persists only for the duration of the server process.
Standard Redis
For traditional Redis deployments, LunaTV uses the Redis backend via a direct connection. Set NEXT_PUBLIC_STORAGE_TYPE=redis and provide the REDIS_URL environment variable containing the connection string.
Upstash Serverless Redis
Upstash connects to the managed serverless Redis service. This backend requires NEXT_PUBLIC_STORAGE_TYPE=upstash plus two variables: UPSTASH_URL and UPSTASH_TOKEN. The implementation uses the @upstash/redis client, which is cached globally to prevent connection overhead across requests as seen in src/lib/upstash.db.ts (lines 11-24).
Kvrocks Persistent Store
Kvrocks is a Redis-compatible persistent key-value store ideal for self-hosted deployments. Configure it using NEXT_PUBLIC_STORAGE_TYPE=kvrocks and the KVROCKS_URL environment variable. According to the source code in src/lib/kvrocks.db.ts (lines 3-13), the constructor supplies this URL to the underlying Redis client and registers a global symbol to enable client reuse across requests.
How Storage Selection Works in LunaTV
The storage backend instantiation logic resides in src/lib/db.ts (lines 9-16). When the server initializes, the createStorage() factory function reads the STORAGE_TYPE constant and returns the appropriate concrete implementation:
function createStorage(): IStorage {
switch (STORAGE_TYPE) {
case 'redis':
return new RedisStorage();
case 'upstash':
return new UpstashRedisStorage();
case 'kvrocks':
return new KvrocksStorage(); // Kvrocks implementation
case 'localstorage':
default:
return null as unknown as IStorage;
}
}
This factory pattern ensures that API handlers interact with storage through a single interface. The singleton db exported from src/lib/db.ts (lines 75-76) forwards method calls—such as getPlayRecord() and addSearchHistory()—to the selected concrete storage class.
Configuring Kvrocks Storage
Kvrocks provides disk-persistent storage with Redis protocol compatibility. To configure Kvrocks for LunaTV:
- Set
NEXT_PUBLIC_STORAGE_TYPE=kvrocks - Define
KVROCKS_URL=redis://user:pass@kvrocks.example.com:6379
The KvrocksStorage class in src/lib/kvrocks.db.ts extends BaseRedisStorage, inheriting standard Redis commands while using the Kvrocks-specific connection string. The global client caching mechanism ensures that subsequent requests reuse the established connection rather than creating new instances.
Configuring Upstash Storage
Upstash requires authentication via URL and token pair. Configure it with:
NEXT_PUBLIC_STORAGE_TYPE=upstashUPSTASH_URL=https://my-upstash.upstash.ioUPSTASH_TOKEN=xxxxxxxxxxxxxxxxxxxx
The UpstashRedisStorage class (defined in src/lib/upstash.db.ts) constructs the @upstash/redis client using these credentials. Like the Kvrocks implementation, it caches the client globally to optimize performance in serverless environments where connection reuse is critical.
Shared Redis Base Implementation
Both Kvrocks and standard Redis backends extend BaseRedisStorage located in src/lib/redis-base.db.ts (lines 44-53). This base class implements the IStorage interface and executes the actual Redis commands (GET, SET, HGETALL, etc.) used for persisting user data. Upstash uses a separate implementation because it requires the specialized @upstash/redis client rather than the standard ioredis or node-redis libraries.
Environment Variable Configuration Examples
Create a .env file in your project root to configure your chosen backend:
# For Kvrocks (Self-hosted persistent storage)
NEXT_PUBLIC_STORAGE_TYPE=kvrocks
KVROCKS_URL=redis://localhost:6666
# For Upstash (Serverless)
# NEXT_PUBLIC_STORAGE_TYPE=upstash
# UPSTASH_URL=https://global-apt-owl-12345.upstash.io
# UPSTASH_TOKEN=AZJgACQgM2YxNTQzMzQtMmYxZC00MzEwLWExZDgtNjQ2YjQwODBhODU0MTRkMGFjMGY5YmU5NGQyNGI3M2Y0MjU2MjRkMWQ2YTY=
# For Standard Redis
# NEXT_PUBLIC_STORAGE_TYPE=redis
# REDIS_URL=redis://localhost:6379
Switching between these configurations requires no code changes; restart the Next.js server to instantiate the new storage class via createStorage().
Accessing Storage in Application Code
Regardless of the backend selected, application code interacts with the storage layer through the singleton db instance:
import { db } from '@/lib/db';
// Save playback progress
await db.savePlayRecord('user-123', 'source-youtube', 'video-456', {
progress: 120,
finished: false,
});
// Retrieve user favorites
const favorites = await db.getFavorites('user-123');
// Add search history
await db.addSearchHistory('user-123', 'django tutorials');
The db object delegates these calls to the concrete storage implementation (Kvrocks, Redis, or Upstash) initialized at startup, ensuring consistent API behavior across all backends.
Summary
- Pluggable Architecture: LunaTV uses the
NEXT_PUBLIC_STORAGE_TYPEenvironment variable to select betweenkvrocks,redis,upstash, andlocalstoragebackends via thecreateStorage()factory insrc/lib/db.ts. - Kvrocks Configuration: Requires
KVROCKS_URLand provides persistent, Redis-compatible storage through theKvrocksStorageclass. - Upstash Configuration: Requires
UPSTASH_URLandUPSTASH_TOKENfor serverless Redis access viaUpstashRedisStorage. - Standard Redis: Uses
REDIS_URLfor traditional Redis deployments, sharing theBaseRedisStorageimplementation with Kvrocks. - Runtime Flexibility: Switch storage backends by changing environment variables; no source code modifications are required thanks to the factory pattern and shared
IStorageinterface.
Frequently Asked Questions
How do I switch from Kvrocks to Upstash without code changes?
Simply update your environment variables. Change NEXT_PUBLIC_STORAGE_TYPE from kvrocks to upstash, replace KVROCKS_URL with UPSTASH_URL and UPSTASH_TOKEN, then restart the server. The createStorage() function in src/lib/db.ts automatically instantiates UpstashRedisStorage instead of KvrocksStorage based on the updated configuration.
What is the difference between Kvrocks and standard Redis in LunaTV?
While both use the same BaseRedisStorage class for command execution, Kvrocks persists data to disk and requires the KVROCKS_URL variable, whereas standard Redis typically operates in memory and uses REDIS_URL. Kvrocks is ideal for self-hosted deployments requiring data durability without separate Redis persistence configuration.
Is localstorage suitable for production use?
No. The localstorage backend is designed for development only, as it stores data in memory and clears when the server restarts. Production deployments must use kvrocks, redis, or upstash to ensure data persistence across restarts and scaling events.
Where is the database connection cached in LunaTV?
Each storage implementation caches its client globally to prevent connection leaks. Kvrocks uses a global symbol registry in src/lib/kvrocks.db.ts, while Upstash caches the client object in src/lib/upstash.db.ts. This ensures that the singleton db instance exported from src/lib/db.ts reuses connections across multiple API requests.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →