Skip to content

Tutorial: Set Up Redis Session Storage

In this tutorial, you will install Redis, configure the Redis session storage backend, and verify that sessions work across server restarts.

Prerequisites

  • A Remix V3 project with session middleware (see the session-middleware tutorial)
  • Redis installed locally or access to a managed Redis service

Step 1: Install Redis

macOS (Homebrew):

bash
brew install redis
brew services start redis

Linux (apt):

bash
sudo apt update && sudo apt install redis-server
sudo systemctl start redis

Docker:

bash
docker run -d --name redis -p 6379:6379 redis:latest

Verify Redis is running:

bash
redis-cli ping
# PONG

Step 2: Add Environment Variables

Add the Redis URL to your .env file:

bash
REDIS_URL=redis://localhost:6379
SESSION_SECRET=your-random-secret-here

Step 3: Configure Redis Session Storage

Replace your current session storage with the Redis backend:

ts
// app/session.ts
import { createCookie } from 'remix/cookie'
import { createRedisSessionStorage } from 'remix/session-storage-redis'

export let sessionCookie = createCookie('__session', {
  httpOnly: true,
  secure: process.env.NODE_ENV === 'production',
  sameSite: 'Lax',
  secrets: [process.env.SESSION_SECRET!],
  maxAge: 60 * 60 * 24 * 7, // 1 week
})

export let sessionStorage = createRedisSessionStorage({
  url: process.env.REDIS_URL!,
  ttl: 60 * 60 * 24 * 7,   // 7 days, matches cookie maxAge
  prefix: 'myapp:session:', // Namespaced key prefix
})

Your router setup and handlers do not change:

ts
// app/server.ts
import { createRouter } from 'remix/fetch-router'
import { session } from 'remix/session-middleware'
import { Session } from 'remix/session'
import { sessionCookie, sessionStorage } from './session.ts'

let router = createRouter({
  middleware: [
    session(sessionCookie, sessionStorage),
  ],
})

router.get(homeRoute, async ({ context }) => {
  let s = context.get(Session)
  let visits = (s.get('visits') ?? 0) + 1
  s.set('visits', visits)
  return new Response(`Visit #${visits}`)
})

Step 4: Use an Existing Redis Client

If your application already uses Redis for caching or other purposes, share the client:

ts
import { createClient } from 'redis'
import { createRedisSessionStorage } from 'remix/session-storage-redis'

let redisClient = createClient({ url: process.env.REDIS_URL! })
await redisClient.connect()

export let sessionStorage = createRedisSessionStorage({
  client: redisClient,
  ttl: 60 * 60 * 24 * 7,
  prefix: 'myapp:session:',
})

Step 5: Test It

  1. Start your server and visit http://localhost:3000
  2. The visit count should increment on each page load
  3. Restart your server (Ctrl+C and start again)
  4. Visit the page again -- the count continues from where it left off (because the session is in Redis, not in process memory)

Inspect the session in Redis:

bash
redis-cli keys "myapp:session:*"
# 1) "myapp:session:a1b2c3d4..."

redis-cli get "myapp:session:a1b2c3d4..."
# {"visits":5}

redis-cli ttl "myapp:session:a1b2c3d4..."
# (integer) 604793

Summary

StepWhat You Did
Install Redisbrew install redis or Docker
Configure storagecreateRedisSessionStorage({ url, ttl, prefix })
Wire up middlewaresession(sessionCookie, sessionStorage) -- same as any backend
TestSessions persist across server restarts

Next Steps

Released under the MIT License.