session-middleware Overview
The remix/session-middleware package provides middleware that connects sessions to your router. It reads the session from the incoming request's cookie, makes it available to your handlers, and saves any changes back to the response automatically. You never need to manually parse cookies or call a save method.
Key Concepts
- Middleware -- Code that runs before and after your route handlers. The session middleware runs on every request.
- Session cookie -- The HTTP cookie that carries the session identifier (or the session data itself, when using cookie storage).
- Session storage -- The backend that persists session data. The middleware uses the storage's
readandsavemethods. - Auto-save -- The middleware saves the session after the handler returns, so you just call
session.set()and the rest happens automatically.
How It Works
The session middleware performs five steps on every request:
Request
1. Parse the session cookie from the Cookie header
2. Load session data from storage (storage.read)
3. Set context.get(Session) for downstream handlers
4. Wait for the handler to return a response
5. Save session changes to storage (storage.save)
6. Add Set-Cookie header to the response
ResponseYou only interact with step 3 -- reading and writing session data in your handlers. Everything else is automatic.
Quick Example
// app/session.ts
import { createCookie } from 'remix/cookie'
import { createCookieSessionStorage } from 'remix/session/cookie-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,
})
export let sessionStorage = createCookieSessionStorage(sessionCookie)// 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(`You have visited ${visits} time(s).`)
})Middleware Ordering
The session middleware must come before any middleware or handler that accesses the session. A typical stack:
let router = createRouter({
middleware: [
formData(), // 1. Parse form data
session(sessionCookie, sessionStorage), // 2. Load session
auth({ schemes: [sessionScheme] }), // 3. Auth reads from session
],
})If auth runs before session, the session will not be loaded yet and the auth scheme will not find a user.
What Gets Saved Automatically
The middleware saves after every request. This includes:
- Values written with
session.set(key, value) - Keys removed with
session.unset(key) - Flash values consumed by
session.get(key) - New session IDs from
session.regenerateId() - Session destruction from
session.destroy()(clears data and removes the cookie)
If nothing changed during the request, the middleware skips the save for efficiency but still refreshes the cookie's maxAge.
How It Fits Together
- remix/session provides the
Sessionclass and storage backends. - remix/session-middleware (this package) is the glue that loads and saves sessions on every request.
- remix/cookie configures the cookie (name, signing, security attributes).
Next Steps
- Tutorial: Add Session Middleware to a Router -- Hands-on guide to integrating sessions.
- API Reference -- Complete documentation of the
session()function.