Let's say I installed latest version of Craft CMS (4.2.5) with no plugins or modules or any file that could modify current user's session. Just plain Craft CMS. When I went through records in Redis I could locate key with a value that matches sessions table for token field.

Redis record

Redis record

PostgreSQL record enter image description here

If Craft CMS stores session information listed on the second picture like id, userId, token , etc. than what for we store the same token in Redis?

Honestly I thought Craft CMS will store all session related data in Redis only.

How does Craft CMS handles user's session with Redis? Why is relational database involved?

1 Answer 1


I partially try to answer my question but It's still unclear to me why session table is used for storing user's session data too. For reference I use PostgreSQL database and "fluent" style declaration in my general.php file.

How session works depends on how you configure your session options in config/general.php file and certain directives in php.ini file.

Here's my testing configuration:


// The amount of time before a user will get logged out due to inactivity
// 180 seconds or 3 minutes

// The amount of time a user’s elevated session will last, 
// which is required for some sensitive actions. 
// 0 to disable elevated session.


; How long session cookie will be stored in browser. 0 until browser is restarted
session.cookie_lifetime = 0

; How long session data will be stored in Redis
session.gc_maxlifetime = 120

How user's session is created

  1. When successfully logged in to the control panel.

    • A row with id, userId, token, dateCreated, dateUpdated and uid is created in session table in PostgreSQL database. These are required information for users table for example to look up a user and update lastLoginDate field which it's value would equal to dateCreated field from our session table
    • A key with value is created in Redis database which looks like the first picture in my question. If we would use file storage system for session instead of Redis than it's content is the same as the content saved in Redis database -> see example

Of course a cookie called whatever you set phpSessionName to is created in user's browser with encoded value which refers to I think uid field in session table. This article helped me before with some unclarities about session so I refer to it.

Note: when you set ->userSessionDuration(0), Redis session key record doesn't contain expire and duration keys which means session exists as long as you keep the control panel opened. There's more to it which I explain bellow.

How user's session behaves when logged in

userSessionDuration is the setting responsible for how long you stay logged in control panel. The session.gc_maxlifetime didn't play a big role in it unless it was set to less than 60 seconds. Apparently this is a time interval how often Craft CMS create XHR request in control panel. If session.gc_maxlifetime = 10 than Redis session record would get removed and we got logged out after 10 seconds.

What I found out if user is logged in and not doing any requests:

  • If ->userSessionDuration(0) and session.gc_maxlifetime = 120 than session record in Redis persists with TTL set to 120. TTL resets back to 120 every 60 seconds because of a XHR request that Craft makes. Field dateUpdated in session table is also updated with a time of XHR request. So you stay logged in as long as you don't hit the button "Log out" or quit browser.
  • If ->userSessionDuration(180) and session.gc_maxlifetime = 120 than session record in Redis persists for 180 seconds with TTL set to 120 if not prolonged by hitting "Keep me signed in" button in control panel. TTL resets back to 120 every 60 seconds because of a XHR request that Craft makes. Field dateUpdated in session table is also updated with a time of XHR request. So you stay logged in for 180 seconds.

So Redis key TTL (time to live) and dateUpdated in session table is something like mtimein PHP session file.

How user's session is destroyed

  1. When you log out from the control panel. Both records from PostgreSQL and Redis are removed.
  2. When ->userSessionDuration(180) is reached. Both records from PostgreSQL and Redis are removed.
  3. When ->userSessionDuration(0), session.gc_maxlifetime = 120 and you quit browser. That is when session.gc_maxlifetime = 120 kicks in because there are no requests incoming to update times in both records and Craft removes a session record from Redis database only. This is unexpected behavior. A record in session table stays even if purgeStaleUserSessionDuration time is reached. I still don't know why "garbage collection" didn't kicked in.

Sum up

Values you set to in userSessionDuration and session.gc_maxlifetime settings are important to keep user logged in according to your needs. dataUpdated in session table and Redis key TTL are also important aspects of session's lifetime which depends on userSessionDuration, session.gc_maxlifetime and activity in the control panel. A session records in session table are used for example for looking up a user in users table with aim to update for example lastLoginDate.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.