Skip to content

session Overview

The remix/session package provides server-side sessions -- key-value stores that persist data across multiple HTTP requests for a single user. Sessions are the standard way to remember things like who is logged in, what is in a shopping cart, or which notification to show next.

Key Concepts

  • Session -- A server-side key-value store tied to a specific user via a cookie. Each user gets their own session. The session lives on the server (or in the cookie itself, depending on the storage backend), and the user's browser only holds a cookie that identifies which session is theirs.
  • Session ID -- A unique, random string that identifies a session. It is stored in the cookie and used by the storage backend to look up the session data.
  • Session storage -- The backend that persists session data between requests. Remix includes built-in storage backends for cookies, the filesystem, memory, Redis, and Memcache.
  • Flash data -- A value that is available for exactly one read. After it is read, it disappears. Flash data is commonly used for success or error messages after a redirect.

The Session API

Once you have a session (via the session middleware), you interact with it through these methods:

MethodDescription
session.get(key)Read a value. Flash values are consumed on read.
session.set(key, value)Write a value. Must be JSON-serializable.
session.has(key)Check if a key exists.
session.unset(key)Remove a key.
session.flash(key, value)Set a one-time value (consumed on the next get).
session.destroy()Mark the session for deletion.
session.regenerateId()Generate a new session ID (keeps data).
session.idThe current session ID (read-only).
session.dataThe raw data object (read-only).

Quick Example

ts
import { Session } from 'remix/session'

router.map(route, async ({ context }) => {
  let session = context.get(Session)

  // Read
  let userId = session.get('userId')

  // Write
  session.set('lastVisit', Date.now())

  // Flash (one-time message)
  let message = session.get('message') // consumed on read

  // Check existence
  if (session.has('cart')) {
    // ...
  }

  // Remove a key
  session.unset('tempData')

  return new Response('OK')
})

Storage Backends

Remix provides several session storage backends. Each implements the same SessionStorage interface, so you can swap between them without changing your application code.

BackendImportBest For
Cookieremix/session/cookie-storageSimple apps, small sessions (under 4KB)
Filesystemremix/session/fs-storageDevelopment, single-server deployments
Memoryremix/session/memory-storageTesting and development only
Redisremix/session-storage-redisProduction, multi-server deployments
Memcacheremix/session-storage-memcacheProduction, multi-server deployments

Stores session data directly in the cookie (encrypted and signed). No server-side storage needed, but limited to about 4KB.

ts
import { createCookie } from 'remix/cookie'
import { createCookieSessionStorage } from 'remix/session/cookie-storage'

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

let sessionStorage = createCookieSessionStorage(sessionCookie)

Filesystem Storage

Stores each session as a JSON file on disk. Simple but does not work with multiple servers.

ts
import { createFsSessionStorage } from 'remix/session/fs-storage'

let sessionStorage = createFsSessionStorage('./sessions')

Memory Storage

Stores sessions in a Map in process memory. Data is lost when the process restarts. Use for testing only.

ts
import { createMemorySessionStorage } from 'remix/session/memory-storage'

let sessionStorage = createMemorySessionStorage()

Redis and Memcache

For production deployments with multiple servers, use Redis or Memcache. Sessions are stored centrally so any server can access any session.

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

let sessionStorage = createRedisSessionStorage({
  url: process.env.REDIS_URL!,
  ttl: 60 * 60 * 24 * 7,
})

See the Redis storage overview and Memcache storage overview for details.

Flash Messages

Flash data is a common pattern for showing one-time messages after a redirect (the Post/Redirect/Get pattern). You set a flash value in one request, and it is available to read exactly once in the next request.

ts
// In the form action (POST /books)
session.flash('notice', 'Book created successfully!')
return new Response(null, { status: 302, headers: { Location: '/books' } })

// In the next page load (GET /books)
let notice = session.get('notice') // "Book created successfully!"
// On the following request, notice is gone:
let notice = session.get('notice') // undefined

Session Security

Two important security practices when working with sessions:

  1. Regenerate the session ID after login. This prevents session fixation attacks, where an attacker sets a known session ID before the user logs in.
ts
session.set('userId', user.id)
session.regenerateId()
  1. Destroy the session on logout. This removes all session data and clears the cookie.
ts
session.destroy()

How It Fits Together

The remix/session package provides the Session class and storage backends. To actually load and save sessions on every request, you need:

Next Steps

Released under the MIT License.