Answers.Body: <p><strike>I partially try to answer my question but It's still unclear to me why <code>session</code> table is used for storing user's session data too.</strike> For reference I use PostgreSQL database and &quot;<a href="https://craftcms.com/docs/4.x/config/#style-map-vs-fluent" rel="nofollow noreferrer">fluent</a>&quot; style declaration in my <em>general.php</em> file.</p>
  <p>How session works depends on how you configure your session options in <em>config/general.php</em> file and certain directives in <em>php.ini</em> file.</p>
  <p>Here's my testing configuration:</p>
  <p><strong>config/general.php</strong></p>
  <pre><code>// The amount of time before a user will get logged out due to inactivity
  // 180 seconds or 3 minutes
  -&gt;userSessionDuration(180)
  
  // The amount of time a user’s elevated session will last, 
  // which is required for some sensitive actions. 
  // 0 to disable elevated session.
  -&gt;elevatedSessionDuration(0)
  </code></pre>
  <p><strong>php.ini</strong></p>
  <pre><code>; 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
  </code></pre>
  <p><strong>How user's session is created</strong></p>
  <ol>
  <li><p>When successfully logged in to the control panel.</p>
  <ul>
  <li>A row with <code>id</code>, <code>userId</code>, <code>token</code>, <code>dateCreated</code>, <code>dateUpdated</code> and <code>uid</code> is created in <code>session</code> table in PostgreSQL database. These are required information for <code>users</code> table for example to look up a user and update <code>lastLoginDate</code> field which it's value would equal to <code>dateCreated</code> field from our <code>session</code> table</li>
  <li>A key with value is created in Redis database which looks like the first picture in my question. If we would use <em>file</em> storage system for session instead of Redis than it's content is the same as the content saved in Redis database -&gt; <a href="https://nystudio107.com/blog/the-case-of-the-missing-php-session#once-more-unto-the-breach-dear-friends" rel="nofollow noreferrer">see example</a></li>
  </ul>
  </li>
  </ol>
  <p>Of course a cookie called whatever you set <code>phpSessionName</code> to is created in user's browser with encoded value which refers to I think <code>uid</code> field in <code>session</code> table. <a href="https://nystudio107.com/blog/the-case-of-the-missing-php-session" rel="nofollow noreferrer">This article</a> helped me before with some unclarities about session so I refer to it.</p>
  <p><em>Note:</em> when you set <code>-&gt;userSessionDuration(0)</code>, Redis session key record doesn't contain <code>expire</code> and <code>duration</code> keys which means session exists as long as you keep the control panel opened. There's more to it which I explain bellow.</p>
  <p><strong>How user's session behaves when logged in</strong></p>
  <p><code>userSessionDuration</code> is the setting responsible for how long you stay logged in control panel. The <code>session.gc_maxlifetime</code> 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 <code>XHR</code> request in control panel. If <code>session.gc_maxlifetime = 10</code> than Redis session record would get removed and we got logged out after 10 seconds.</p>
  <p>What I found out if user is logged in and not doing any requests:</p>
  <ul>
  <li>If <code>-&gt;userSessionDuration(0)</code> and <code>session.gc_maxlifetime = 120</code> than session record in Redis persists with <code>TTL</code> set to <code>120</code>. <code>TTL</code> resets back to <code>120</code> every 60 seconds because of a <code>XHR</code> request that Craft makes. Field <code>dateUpdated</code> in <code>session</code> table is also updated with a time of <code>XHR</code> request. So you stay logged in as long as you don't hit the button &quot;Log out&quot; or quit browser.</li>
  <li>If <code>-&gt;userSessionDuration(180)</code> and <code>session.gc_maxlifetime = 120</code> than session record in Redis persists for 180 seconds with <code>TTL</code> set to <code>120</code> if not prolonged by hitting &quot;Keep me signed in&quot; button in control panel. <code>TTL</code> resets back to <code>120</code> every 60 seconds because of a <code>XHR</code> request that Craft makes. Field <code>dateUpdated</code> in <code>session</code> table is also updated with a time of <code>XHR</code> request. So you stay logged in for 180 seconds.</li>
  </ul>
  <p>So <a href="https://redis.io/commands/ttl/" rel="nofollow noreferrer">Redis key <code>TTL</code></a> (time to live) and <code>dateUpdated</code> in <code>session</code> table is something like <a href="https://www.poftut.com/what-is-mtime-in-linux-and-find-command/" rel="nofollow noreferrer"><code>mtime</code>in PHP session file</a>.</p>
  <p><strong>How user's session is destroyed</strong></p>
  <ol>
  <li>When you log out from the control panel. Both records from PostgreSQL and Redis are removed.</li>
  <li>When <code>-&gt;userSessionDuration(180)</code> is reached. Both records from PostgreSQL and Redis are removed.</li>
  <li>When <code>-&gt;userSessionDuration(0)</code>, <code>session.gc_maxlifetime = 120</code> and you quit browser. That is when <code>session.gc_maxlifetime = 120</code> 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 <code>session</code> table stays even if <code>purgeStaleUserSessionDuration</code> time is reached. I still don't know why &quot;garbage collection&quot; didn't kicked in.</li>
  </ol>
  <p><strong>Sum up</strong></p>
  <p>Values you set to in <code>userSessionDuration</code> and <code>session.gc_maxlifetime</code> settings are important to keep user logged in according to your needs. <code>dataUpdated</code> in <code>session</code> table and Redis key <code>TTL</code> are also important aspects of session's lifetime which depends on <code>userSessionDuration</code>, <code>session.gc_maxlifetime</code> and activity in the control panel. A session records in <code>session</code> table are used for example for looking up a user in <code>users</code> table with aim to update for example <code>lastLoginDate</code>.</p>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2022-10-03T10:10:49.153Z
Answers.LastActivityDate: 2022-10-04T09:03:15.103Z
Answers.LastEditDate: 2022-10-04T09:03:15.103Z
Answers.UserDisplayName: Dominik Krulak
Body: <p>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 <code>sessions</code> table for <code>token</code> field.</p>
  <p><strong>Redis record</strong></p>
  <p><a href="https://i.sstatic.net/mw4KI.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/mw4KI.png" alt="Redis record" /></a></p>
  <p><strong>PostgreSQL record</strong>
  <a href="https://i.sstatic.net/DaIOq.png" rel="nofollow noreferrer"><img src="https://i.sstatic.net/DaIOq.png" alt="enter image description here" /></a></p>
  <p>If Craft CMS stores session information listed on the second picture like <code>id</code>, <code>userId</code>, <code>token</code> , etc. than what for we store the same token in Redis?</p>
  <p>Honestly I thought Craft CMS will store all session related data in Redis only.</p>
  <p>How does Craft CMS handles user's session with Redis? Why is relational database involved?</p>
  
Tags: <session><redis>
Title: How does Craft CMS handle user's session with Redis
ThreadText: # How does Craft CMS handle user's session with Redis
  
  (Asked by: username_0 on 2022-09-26)
  
  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](https://i.sstatic.net/mw4KI.png)](https://i.sstatic.net/mw4KI.png)
  
  **PostgreSQL record**
  [![enter image description here](https://i.sstatic.net/DaIOq.png)](https://i.sstatic.net/DaIOq.png)
  
  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?
  
  **Tags:** session, redis
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_0 on 2022-10-03. Score: 3
  
  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](https://craftcms.com/docs/4.x/config/#style-map-vs-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:
  
  **config/general.php**
  
  ```
  // The amount of time before a user will get logged out due to inactivity
  // 180 seconds or 3 minutes
  ->userSessionDuration(180)
  
  // The amount of time a user’s elevated session will last, 
  // which is required for some sensitive actions. 
  // 0 to disable elevated session.
  ->elevatedSessionDuration(0)
  
  ```
  
  **php.ini**
  
  ```
  ; 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](https://nystudio107.com/blog/the-case-of-the-missing-php-session#once-more-unto-the-breach-dear-friends)
  
  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](https://nystudio107.com/blog/the-case-of-the-missing-php-session) 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`](https://redis.io/commands/ttl/) (time to live) and `dateUpdated` in `session` table is something like [`mtime`in PHP session file](https://www.poftut.com/what-is-mtime-in-linux-and-find-command/).
  
  **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`.
  
  
  ---
  
  