{"id":17005,"library":"express-session","title":"Express Session Middleware","description":"express-session is a robust and widely-used session middleware for Express.js applications, currently stable at version 1.19.0. It provides server-side session storage, managing session IDs via cookies while keeping the actual session data on the server, which is a key security differentiator compared to client-side cookie storage. While the core package offers a default `MemoryStore` for development and debugging, it explicitly warns against its use in production due to memory leak risks and lack of scalability, promoting a rich ecosystem of compatible external session stores. The project maintains a steady release cadence, with recent updates focusing on features like dynamic cookie options, improved security tooling, and dependency updates, ensuring ongoing compatibility and enhancements for Node.js environments (supporting Node.js >= 0.8.0). It has evolved to directly manage session cookies, making the `cookie-parser` middleware optional and recommending careful use if both are present to avoid secret mismatches.","status":"active","version":"1.19.0","language":"javascript","source_language":"en","source_url":"https://github.com/expressjs/session","tags":["javascript"],"install":[{"cmd":"npm install express-session","lang":"bash","label":"npm"},{"cmd":"yarn add express-session","lang":"bash","label":"yarn"},{"cmd":"pnpm add express-session","lang":"bash","label":"pnpm"}],"dependencies":[{"reason":"This package is middleware for the Express.js framework.","package":"express","optional":false}],"imports":[{"note":"The primary export is a default function that creates the middleware.","wrong":"import { session } from 'express-session'","symbol":"session","correct":"import session from 'express-session'"},{"note":"CommonJS require imports the default middleware factory function.","wrong":"const { session } = require('express-session')","symbol":"session","correct":"const session = require('express-session')"},{"note":"To implement a custom session store, you would typically extend the `Store` class, which is a named export for TypeScript purposes. However, the `Store` class is not directly exported for runtime use as a typical named import, it's more for type definitions and extension.","wrong":"import { SessionStore } from 'express-session'; // Incorrect export name for type","symbol":"SessionStore","correct":"import { Store } from 'express-session'; // For type hinting custom stores"}],"quickstart":{"code":"const express = require('express');\nconst session = require('express-session');\nconst app = express();\nconst port = 3000;\n\n// WARNING: The default MemoryStore is NOT production-ready.\n// For production, use a compatible session store like connect-redis, connect-mongo, or memorystore.\n// For a list of stores, see compatible session stores section in the README.\napp.use(session({\n  secret: process.env.SESSION_SECRET ?? 'a very strong secret key that should be in an environment variable', // ALWAYS use a strong, environment-variable-backed secret\n  resave: false, // Don't save session if unmodified\n  saveUninitialized: true, // Save new but uninitialized sessions (e.g., before user logs in)\n  cookie: {\n    secure: process.env.NODE_ENV === 'production', // Use secure cookies in production (requires HTTPS)\n    httpOnly: true, // Prevent client-side JavaScript access to cookie (mitigates XSS)\n    maxAge: 24 * 60 * 60 * 1000 // Session expires after 24 hours (in milliseconds)\n  }\n}));\n\napp.get('/', (req, res) => {\n  if (req.session.views) {\n    req.session.views++;\n    res.send(`<h1>Welcome back!</h1><p>You have visited this page ${req.session.views} times.</p><p>Your session ID is: ${req.sessionID}</p>`);\n  } else {\n    req.session.views = 1;\n    res.send(`<h1>Hello, New User!</h1><p>You have visited this page ${req.session.views} time.</p><p>Your session ID is: ${req.sessionID}</p>`);\n  }\n});\n\napp.listen(port, () => {\n  console.log(`Server listening at http://localhost:${port}`);\n  console.log('Try visiting a few times and then refresh after some time to see the session count.');\n  console.log('For production, ensure `secure: true` for cookies and that your app runs over HTTPS.');\n});","lang":"javascript","description":"This example demonstrates how to set up `express-session` with basic configuration for a view counter. It highlights essential cookie options like `secure`, `httpOnly`, and `maxAge`, and includes a critical warning about not using the default `MemoryStore` in production, emphasizing the use of environment variables for secrets."},"warnings":[{"fix":"Implement a production-ready session store, such as `connect-redis`, `connect-mongo`, `memorystore`, or other compatible solutions listed in the `express-session` documentation.","message":"The default `MemoryStore` provided by `express-session` is explicitly not designed for production environments. It is known to leak memory under most conditions and does not scale past a single process, making it suitable only for debugging and development.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Generally, remove `cookie-parser` if `express-session` is handling session cookies. If `cookie-parser` is required for other (non-session) cookies, ensure that both middlewares use the *same* `secret` key.","message":"Since version 1.5.0, `express-session` directly reads and writes cookies on `req`/`res`. Using `cookie-parser` middleware concurrently can lead to issues, especially if the `secret` used by `express-session` differs from that used by `cookie-parser`.","severity":"gotcha","affected_versions":">=1.5.0"},{"fix":"Consistently use `maxAge` (in milliseconds) for controlling cookie expiration, and avoid setting `expires` directly.","message":"When configuring cookie options, if both `expires` and `maxAge` are set, the last one defined in the `cookie` object will take precedence. It is generally recommended to use only `maxAge`.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Explicitly set `resave` to `false` unless your session store specifically requires it. Most modern stores handle session modifications efficiently without needing `resave: true`.","message":"The `resave` option's default value of `true` has been deprecated and will change in future versions. Setting `resave: true` can create race conditions in certain session stores.","severity":"deprecated","affected_versions":">=1.0.0"},{"fix":"Ensure that any dynamically generated or configured `expires` dates are valid `Date` objects. It is best practice to use `maxAge` instead of `expires` for session cookies.","message":"The `cookie` dependency was updated to `0.6.0` in `express-session` v1.18.0, which included a fix to reject invalid dates for the `expires` option. Applications that might have implicitly handled or passed malformed dates to `expires` could experience errors.","severity":"breaking","affected_versions":">=1.18.0"},{"fix":"Always keep `cookie.httpOnly` set to `true` (the default) unless there is a very specific, well-understood requirement for client-side JavaScript to access the session cookie.","message":"Setting `cookie.httpOnly` to `false` (it defaults to `true`) allows client-side JavaScript to access the session cookie via `document.cookie`. This significantly increases the risk of Cross-Site Scripting (XSS) attacks leading to session hijacking.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-22T00:00:00.000Z","next_check":"2026-07-21T00:00:00.000Z","problems":[{"fix":"Provide a strong, unpredictable string or an array of strings as the `secret` value in the `session()` options. It should be stored in an environment variable for security.","cause":"The `secret` option, which is mandatory for session signing, was either omitted or provided with an invalid type (e.g., `null`, `undefined`, a number).","error":"Error: secret must be a string or array of strings"},{"fix":"Ensure you are calling the imported `session` module to create the middleware: `app.use(session({ ... }))`. For CommonJS: `const session = require('express-session');`. For ESM: `import session from 'express-session';`.","cause":"This typically occurs when attempting to use `express-session` as a direct middleware function, rather than calling the imported module to get the middleware factory. This is often an ESM `import` or CommonJS `require` misuse.","error":"TypeError: session is not a function"},{"fix":"Replace the default `MemoryStore` with a production-grade, persistent session store like `connect-redis`, `connect-mongo`, or `memorystore`.","cause":"This warning explicitly states that the default `MemoryStore` is being used in an environment that is likely production, which will lead to memory leaks and scalability issues.","error":"Warning: connect.session() MemoryStore is not designed for a production environment, as it will leak memory, and will not scale past a single process."},{"fix":"Remove `cookie-parser` if `express-session` is sufficient for your cookie needs. If `cookie-parser` is still needed for other reasons, ensure both `express-session` and `cookie-parser` use the exact same `secret` value.","cause":"A conflict or misconfiguration between `express-session` and `cookie-parser`, particularly if both are used with different `secret` options, or if `cookie-parser` is used redundantly as `express-session` handles cookie parsing internally.","error":"CookieParseError: Invalid cookie header"},{"fix":"Inspect the session store for malformed data. If using a custom store, verify its `get` and `set` methods. If using an existing store, check for recent updates to `express-session` or the store implementation that might address data handling bugs.","cause":"The session store returned corrupted or unparseable session data, or an internal error occurred during session deserialization. This can sometimes happen with store migrations or data integrity issues.","error":"UnhandledPromiseRejectionWarning: Error: Bad session data"}],"ecosystem":"npm","meta_description":null}