Skip to content

remix/session

The remix/session package provides the core session API for Remix V3. Sessions are server-side key-value stores associated with a user via a cookie. They are used to persist data across requests --- login state, flash messages, shopping carts, and more.

Installation

The remix/session package is included with Remix. No additional installation is required.

ts
import { createSession, createSessionId, Session } from 'remix/session'

createSession(data?)

Creates a new Session instance with optional initial data.

ts
function createSession(data?: Record<string, unknown>): Session

Parameters:

ParameterTypeDescription
dataRecord<string, unknown>Optional. Initial key-value pairs to populate the session with.

Example:

ts
import { createSession } from 'remix/session'

// Empty session
let session = createSession()

// Session with initial data
let session = createSession({
  userId: 42,
  theme: 'dark',
})

createSessionId()

Generates a cryptographically random session ID string.

ts
function createSessionId(): string

Returns a unique string suitable for use as a session identifier. You typically do not need to call this directly --- session storage backends generate IDs automatically. It is exposed for advanced use cases such as custom storage implementations.

Example:

ts
import { createSessionId } from 'remix/session'

let id = createSessionId()
// e.g. "a1b2c3d4e5f6..."

Session Context Key

The Session export serves double duty: it is both the session class and a context key. When used with context.get(Session), it retrieves the current request's session (set by the session middleware).

ts
import { Session } from 'remix/session'

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

Session Class API

session.get(key)

Reads a value from the session.

ts
session.get(key: string): unknown

Returns the value associated with the key, or undefined if the key does not exist. Flash values are returned once and then automatically removed.

Example:

ts
let userId = session.get('userId')   // number | undefined
let theme = session.get('theme')     // string | undefined
let flash = session.get('message')   // string | undefined (consumed on read)

session.set(key, value)

Writes a value to the session.

ts
session.set(key: string, value: unknown): void

Values must be JSON-serializable: strings, numbers, booleans, arrays, plain objects, and null.

Example:

ts
session.set('userId', 42)
session.set('theme', 'dark')
session.set('cart', [{ productId: 1, quantity: 2 }])

session.has(key)

Checks whether a key exists in the session.

ts
session.has(key: string): boolean

Returns true if the key exists (including flash keys that have not yet been read), false otherwise.

Example:

ts
if (session.has('userId')) {
  // User is logged in
}

session.unset(key)

Removes a single key from the session.

ts
session.unset(key: string): void

Example:

ts
session.unset('cart')
// session.get('cart') now returns undefined

session.flash(key, value)

Sets a value that is available for one subsequent read only. After it is read with session.get(key), it is automatically removed.

ts
session.flash(key: string, value: unknown): void

Flash values are ideal for success or error messages after a redirect (the Post/Redirect/Get pattern).

Example:

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

// In the next request's handler
let message = session.get('message')  // "Book created successfully!"
// On the following request:
let message = session.get('message')  // undefined

session.destroy()

Marks the session for deletion. All data is cleared, and the session cookie will be removed from the response. The deletion is carried out by the session middleware when it saves the response.

ts
session.destroy(): void

Example:

ts
// Logout handler
session.destroy()
return new Response(null, { status: 302, headers: { Location: '/login' } })

session.regenerateId(deleteOld?)

Generates a new session ID while preserving all session data. This is a security best practice after authentication state changes (login, privilege escalation) to prevent session fixation attacks.

ts
session.regenerateId(deleteOld?: boolean): void

Parameters:

ParameterTypeDefaultDescription
deleteOldbooleantrueWhether to delete the old session from storage. Set to false to keep the old session (rare).

Example:

ts
// After a successful login
session.set('userId', user.id)
session.regenerateId()
// The session now has a new ID, but the same data

session.id

The current session ID. A read-only string property.

ts
session.id: string

Example:

ts
console.log(session.id)  // "a1b2c3d4e5f6..."

session.data

The raw session data object. A read-only property that returns the underlying key-value store. Prefer using get, set, has, and unset instead of accessing this directly.

ts
session.data: Record<string, unknown>

Example:

ts
console.log(session.data)  // { userId: 42, theme: 'dark' }

SessionStorage Interface

Session storage backends implement the SessionStorage interface:

ts
interface SessionStorage {
  read(cookie: string): Promise<Session>
  save(session: Session): Promise<string>
}
MethodDescription
read(cookie)Parses the cookie value, retrieves session data from storage, and returns a Session instance. If the cookie is empty or the session does not exist, returns a new empty session.
save(session)Persists the session data to storage and returns the cookie value to set in the response. Handles creating new sessions, updating existing ones, and deleting destroyed sessions.

You typically do not interact with SessionStorage directly. The session middleware calls read and save automatically.


Sub-Exports

Stores session data directly inside the cookie (encrypted and signed). No server-side storage is needed.

ts
import { createCookieSessionStorage } from 'remix/session/cookie-storage'
ts
function createCookieSessionStorage(cookie: Cookie): SessionStorage

Parameters:

ParameterTypeDescription
cookieCookieA cookie created with createCookie() from remix/cookie. The cookie's secrets are used to encrypt and sign the session data.

Pros: No external dependencies, works everywhere, zero latency. Cons: Limited to approximately 4KB of data, session data is sent with every request.

Example:

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)

remix/session/fs-storage

Stores session data as files on the local filesystem.

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

createFsSessionStorage(directory)

ts
function createFsSessionStorage(directory: string): SessionStorage

Parameters:

ParameterTypeDescription
directorystringThe directory path where session files are stored. Created automatically if it does not exist.

Pros: Simple, no extra software needed. Cons: Does not work with multiple servers (each server has its own files). Not suitable for serverless or container deployments where the filesystem is ephemeral.

Example:

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

let sessionStorage = createFsSessionStorage('./sessions')

Each session is stored as a separate JSON file (e.g. ./sessions/a1b2c3d4e5f6.json).


remix/session/memory-storage

Stores session data in-process memory. Intended for testing and development only.

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

createMemorySessionStorage()

ts
function createMemorySessionStorage(): SessionStorage

Takes no arguments. All session data is stored in a Map in memory.

Pros: Fast, no dependencies, no setup. Cons: Data is lost when the process restarts. Not suitable for production. Does not work with multiple servers.

Example:

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

let sessionStorage = createMemorySessionStorage()

Complete Example

ts
// app/session.ts
import { createCookie } from 'remix/cookie'
import { createFsSessionStorage } from 'remix/session/fs-storage'

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 = createFsSessionStorage('./sessions')
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.map(route, async ({ context }) => {
  let s = context.get(Session)

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

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

  // Flash (one-time read)
  let message = s.get('message')

  // Destroy (logout)
  // s.destroy()

  // Regenerate ID (after login)
  // s.regenerateId()
})

Released under the MIT License.