How to Set Up LunaTV with Upstash: Complete Configuration Guide

To set up LunaTV with Upstash, configure three environment variables—NEXT_PUBLIC_STORAGE_TYPE=upstash, UPSTASH_URL, and UPSTASH_TOKEN—and the application will automatically instantiate UpstashRedisStorage from src/lib/upstash.db.ts to persist user accounts, play records, and favorites.

LunaTV, an open-source media streaming platform from MoonTechLab/LunaTV, uses a pluggable storage architecture defined by the IStorage interface. While the application defaults to local storage for development, production deployments require a persistent backend like Upstash Redis to handle user data, search history, and favorites across server restarts.

Select Upstash as the Storage Backend

LunaTV determines which storage provider to use by reading the NEXT_PUBLIC_STORAGE_TYPE environment variable at runtime. In src/lib/db.ts, the application switches between localstorage, redis, upstash, and kvrocks implementations.

Set the variable to upstash to trigger instantiation of the UpstashRedisStorage class:

// src/lib/db.ts – storage selection logic
const STORAGE_TYPE =
  (process.env.NEXT_PUBLIC_STORAGE_TYPE as
    | 'localstorage'
    | 'redis'
    | 'upstash'
    | 'kvrocks'
    | undefined) || 'localstorage';

// ... later in the factory function:
case 'upstash':
  return new UpstashRedisStorage();

The factory defaults to localstorage if the variable is undefined, making the explicit upstash value required for cloud deployments.

Provide Upstash Connection Credentials

The UpstashRedisStorage class creates a singleton Redis client using the @upstash/redis package. This requires two sensitive environment variables consumed in src/lib/upstash.db.ts (lines 511–526):

  • UPSTASH_URL – The HTTP endpoint of your Upstash Redis instance.
  • UPSTASH_TOKEN – The read/write authentication token.
// src/lib/upstash.db.ts – client initialization (lines 511-526)
const upstashUrl = process.env.UPSTASH_URL;
const upstashToken = process.env.UPSTASH_TOKEN;

if (!upstashUrl || !upstashToken) {
  throw new Error('UPSTASH_URL and UPSTASH_TOKEN env variables must be set');
}

client = new Redis({
  url: upstashUrl,
  token: upstashToken,
  retry: { 
    retries: 3, 
    backoff: (c) => Math.min(1000 * Math.pow(2, c), 30000) 
  },
});

The client implements exponential backoff for resilience, retrying failed connections up to three times with a maximum delay of 30 seconds.

Configure the Environment

Create a .env.local file in your project root with the three required variables. Replace the placeholder values with your actual Upstash credentials from the Upstash Console:


# Storage driver selection (src/lib/db.ts line 11)

NEXT_PUBLIC_STORAGE_TYPE=upstash

# Upstash Redis connection (src/lib/upstash.db.ts lines 511-516)

UPSTASH_URL=https://my-upstash-redis.upstash.io
UPSTASH_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

LunaTV uses NEXT_PUBLIC_STORAGE_TYPE to route all database operations through the Upstash implementation rather than the default local storage fallback.

Deploy and Verify the Integration

With the environment variables configured, start the Next.js application:

npm run dev

# or for production:

npm start

On first launch, the UpstashRedisStorage constructor lazily initializes the Redis client, and the DbManager automatically triggers data migrations (lines 447–464 in src/lib/upstash.db.ts). These migrations convert legacy flat-key structures into optimized Redis hashes. Watch the server console for migration logs indicating successful schema updates.

Confirm the setup by checking the server logs for the message "Upstash Redis client created successfully" (line 32 in src/lib/upstash.db.ts). Test persistence by registering a new user via the API:

curl -X POST https://your-domain.com/api/login \
  -H "Content-Type: application/json" \
  -d '{"username":"alice","password":"Secret123"}'

This request is handled by src/app/api/login/route.ts, which calls db.registerUser(). With Upstash configured, the user record persists in your Redis instance rather than in-memory storage. Verify the data exists by querying the sys:users set directly through the Upstash CLI or REST API:

curl -X GET "https://my-upstash-redis.upstash.io/smembers/sys:users" \
  -H "Authorization: Bearer $UPSTASH_TOKEN"

Summary

  • Set NEXT_PUBLIC_STORAGE_TYPE=upstash in src/lib/db.ts to activate the Upstash storage driver.
  • Provide UPSTASH_URL and UPSTASH_TOKEN to the singleton client initialized in src/lib/upstash.db.ts (lines 511–526).
  • Automatic migrations handle schema updates when the server boots, converting legacy data to Redis hashes.
  • Verify connectivity through server logs and by querying the sys:users set via the Upstash REST API.

Frequently Asked Questions

What storage backends does LunaTV support besides Upstash?

According to the source code in src/lib/db.ts, LunaTV supports four storage implementations: localstorage (default for development), redis (standard Redis), upstash (Upstash Redis), and kvrocks. Each implements the IStorage interface, allowing seamless swapping without code changes.

Why does LunaTV require both UPSTASH_URL and UPSTASH_TOKEN?

The UpstashRedisStorage class uses these variables to construct the @upstash/redis client with HTTP-based authentication. The URL identifies your specific Redis database endpoint, while the token provides authenticated access. Missing either variable triggers an explicit error throw at lines 514–516 in src/lib/upstash.db.ts.

How does LunaTV handle connection failures to Upstash?

The Redis client configuration in src/lib/upstash.db.ts implements a retry strategy with exponential backoff. It attempts failed operations three times, using a backoff calculation of Math.min(1000 * Math.pow(2, c), 30000) where c is the attempt count, ensuring maximum retry intervals cap at 30 seconds.

Where is user data stored when using Upstash with LunaTV?

User accounts are stored in the sys:users Redis set, while individual user profiles, play records, and favorites are maintained as Redis hashes. The src/lib/upstash.db.ts file handles these data structures, and the src/app/api/login/route.ts endpoint writes authentication data through this layer.

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:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →