Session
A session lets Drupal recognize one visitor across page requests. The server keeps the data and a cookie holds the ID that points to it.
A session is how Drupal remembers one visitor between page requests. The server keeps the session data, by default in a database table, and the browser holds a cookie with a session ID that points to it. On each request the cookie tells Drupal which stored session belongs to the visitor, and that is how a login lasts from one page to the next.
How sessions work in Drupal 11
Drupal's session code lives in Drupal\Core\Session. The session_manager service is a SessionManager, built on Symfony's native session storage. The default SessionHandler writes to the sessions table. It hashes the ID from the cookie before using it as the key. Each row also records the user ID: 0 for an anonymous visitor, the account number for a logged-in one.
The cookie name starts with SESS on plain HTTP and SSESS on HTTPS, followed by 32 characters of a hash. The hash comes from the cookie domain when one is set, otherwise from the host and base path. The result is a cookie name that looks like a random string.
Drupal starts sessions lazily. If the request has no session cookie, nothing is started until code stores something in the session. A visitor who only reads pages never receives a cookie, and the source code says why: it allows HTTP proxies to cache anonymous page views. Sessions are not supported on the command line, so Drush commands run without one.
Login, logout and the session ID
When a user logs in, the function user_login_finalize() sets the current account, writes a log entry, saves the login time and migrates the session to a new ID. The new ID protects against session fixation, where an attacker plants a known ID before the victim logs in. On logout, user_logout() destroys the session through the session manager and replaces the account with an anonymous one. Drupal 11.5 deprecates both functions in favor of the LoginFinalizer and LogoutFinalizer services. See user authentication for the wider picture and authenticated for what a logged-in visitor is.
Example: session lifetime settings
Lifetimes live in the session.storage.options parameter of sites/default/services.yml. Core ships the values in default.services.yml. Copy the whole block from there, then change only what you need. This example makes the cookie end when the browser closes and keeps session data on the server for one day.
parameters:
session.storage.options:
gc_probability: 1
gc_divisor: 100
gc_maxlifetime: 86400
cookie_lifetime: 0
cookie_samesite: Lax
name_suffix: ''
Rebuild the container afterwards, for example with drush cr. The two lifetimes do different jobs. cookie_lifetime says when the browser drops the cookie. gc_maxlifetime says how long the server may keep the data before garbage collection removes it. A visitor loses the login when either one runs out.
Common mistakes
- Changing only one lifetime. Raising
cookie_lifetimedoes not help ifgc_maxlifetimeis shorter, because the server data is gone first. - Writing to the session on every anonymous request. Each visitor then gets a cookie, and the caching benefit of lazy sessions is lost.
- Testing session behavior from the command line. Sessions do nothing there; test in a browser or with an HTTP client that keeps cookies.
- Assuming a session means a login. The table holds anonymous sessions too, so check the user ID, not the existence of a row.
For marketing and content teams
If editors report being logged out too soon, the cause is usually one of the two lifetime values above. Ask your developers to check them. Visitors who only read your pages normally get no Drupal session cookie. If a module or form changes that for anonymous visitors, page caching can be affected, so raise it with your developers before you add such a feature. Read more about caching to see why this matters.