Web Analytics Made Easy - Statcounter
BaseKV
Sign InSign Up
Back to Articles

Next.js Persistent Session Store Guide

Implementing secure, persistent sessions in Next.js App Router using server actions and a key-value database.

BaseKV Team6 min read
nextjstutorialauthentication

Handling user sessions in Next.js has evolved significantly with the introduction of the App Router and Server Actions. Gone are the days of simple express-session middleware.

In a serverless environment (like Vercel or AWS Lambda), your backend is ephemeral. You cannot store sessions in memory variables because the server instance might disappear between requests. You need a Next.js persistent session store.

Cookies vs. Database Sessions

There are two main ways to persist state:

  1. Stateless (JWT in Cookie): You encrypt all user data into a token and send it to the browser.

    • Pros: Fast, no database lookup.
    • Cons: Limited size (4KB), hard to invalidate (you can't "log out" a user easily without rotation), potential security risks if not handled perfectly.
  2. Stateful (Session ID in Cookie + Database): You store just an ID in the cookie. The actual data lives in a database.

    • Pros: Secure, easy to revoke (just delete the DB key), unlimited data size.
    • Cons: Requires a database lookup on every request.

For most robust applications, the stateful approach is preferred for security and control. But you need a fast database.

Implementing with Server Actions

In Next.js 14+, you can use Server Actions to manage login flows.

'use server'

import { cookies } from 'next/headers'
import { redirect } from 'next/navigation'
// Import a Redis-compatible client
import redis from '@/lib/redis' 

export async function login(formData: FormData) {
  const email = formData.get('email')
  
  // 1. Validate user...
  const user = await validateUser(email)
  
  // 2. Create a session
  const sessionId = crypto.randomUUID()
  
  // 3. Store in persistent KV store
  // Set TTL to 7 days (60 * 60 * 24 * 7)
  await redis.set(`session:${sessionId}`, JSON.stringify(user), 'EX', 604800)
  
  // 4. Set cookie
  cookies().set('session_id', sessionId, { 
    httpOnly: true,
    secure: process.env.NODE_ENV === 'production',
    maxAge: 604800,
    path: '/',
  })
  
  redirect('/dashboard')
}

Why "Persistent" Matters

If you use a standard Redis instance without persistence (AOF/RDB) configured, a server restart wipes out all active sessions. Your execution environment (Vercel) doesn't control the database uptime.

Using a persistent key-value store ensures that even if your storage provider restarts or upgrades, your users stay logged in. This is critical for user retention.

Conclusion

Next.js demands a stateless application logic but stateful data storage. bridging this gap with a fast, persistent key-value store gives you the best of both worlds: the security of server-side sessions with the speed of the edge.

If you are looking for a zero-config, persistent solution, check out BaseKV.