# How to Configure Storage for LunaTV: Kvrocks, Redis, and Upstash Setup Guide

> Learn how to configure storage for LunaTV with Kvrocks, Redis, and Upstash. Easily switch between backends using the NEXT_PUBLIC_STORAGE_TYPE variable without code changes.

- Repository: [MoonTechLab/LunaTV](https://github.com/MoonTechLab/LunaTV)
- Tags: how-to-guide
- Published: 2026-09-09

---

**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`](https://github.com/MoonTechLab/LunaTV/blob/main/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`](https://github.com/MoonTechLab/LunaTV/blob/main/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`](https://github.com/MoonTechLab/LunaTV/blob/main/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:

```typescript
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`](https://github.com/MoonTechLab/LunaTV/blob/main/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:

1. Set `NEXT_PUBLIC_STORAGE_TYPE=kvrocks`
2. Define `KVROCKS_URL=redis://user:pass@kvrocks.example.com:6379`

The **`KvrocksStorage`** class in [`src/lib/kvrocks.db.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/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:

1. `NEXT_PUBLIC_STORAGE_TYPE=upstash`
2. `UPSTASH_URL=https://my-upstash.upstash.io`
3. `UPSTASH_TOKEN=xxxxxxxxxxxxxxxxxxxx`

The **`UpstashRedisStorage`** class (defined in [`src/lib/upstash.db.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/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`](https://github.com/MoonTechLab/LunaTV/blob/main/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:

```bash

# 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:

```typescript
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_TYPE` environment variable to select between `kvrocks`, `redis`, `upstash`, and `localstorage` backends via the `createStorage()` factory in [`src/lib/db.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/db.ts).
- **Kvrocks Configuration**: Requires `KVROCKS_URL` and provides persistent, Redis-compatible storage through the `KvrocksStorage` class.
- **Upstash Configuration**: Requires `UPSTASH_URL` and `UPSTASH_TOKEN` for serverless Redis access via `UpstashRedisStorage`.
- **Standard Redis**: Uses `REDIS_URL` for traditional Redis deployments, sharing the `BaseRedisStorage` implementation with Kvrocks.
- **Runtime Flexibility**: Switch storage backends by changing environment variables; no source code modifications are required thanks to the factory pattern and shared `IStorage` interface.

## 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`](https://github.com/MoonTechLab/LunaTV/blob/main/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`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/kvrocks.db.ts), while Upstash caches the client object in [`src/lib/upstash.db.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/upstash.db.ts). This ensures that the singleton `db` instance exported from [`src/lib/db.ts`](https://github.com/MoonTechLab/LunaTV/blob/main/src/lib/db.ts) reuses connections across multiple API requests.