Technical documentation on how the user session clearing process is implemented

This question was triggered by the new persistent session feature [1].

In the past (before the introduction of persistent session), in the context of mobile apps, I used to rely on the offline session feature (offline_session scope) to keep users logged in (assuming a single-site scenario without an external Infinispan). This was because sessions were persisted in the database tables offline_client_session and offline_user_session. Additionally, I used the Offline Session Max and Offline Session Idle settings, which were decoupled from the SSO Session Idle and SSO Session Max settings, allowing for greater flexibility.
With the introduction of persistent session, both online and offline sessions are now stored in the same database tables, with an additional field indicating the offline flag. According to the article [1], the recommendation is to move to online sessions, as offline sessions are intended for other specific use cases.
Therefore, I assume that to handle long expiration for mobile apps, we need to increase the Realm SSO Session Max. However, this will also increase the number of online sessions.

To monitor the cleanup process, I was wondering if there is any technical documentation explaining how sessions are managed and cleaned up. So far, my understanding is that a background process is responsible for cleaning up expired SSO user sessions and their related client sessions. However, I have noticed in some scenarios that certain client sessions are only deleted when interacting with the client sessions endpoint —perhaps they are only marked as expired but not immediately purged. I’m not entirely sure about this behavior. My concern is that I observed some expired client sessions (not associated with an existing user session) that were not cleaned up in the database. However, I was unable to reproduce the scenario to report it as an issue.

I’d appreciate any insights on this topic.

[1] Keeping users logged in with Keycloak 25 - Keycloak

Just answering to myself (and to help others):
Yes, you are right :grinning_face_with_smiling_eyes:.

The persistence session feature stores the sessions (online and offline) in the OFFLINE_USER_SESSION and OFFLINE_CLIENT_SESSION tables.
There is a cleanup process for both online and offline sessions, which utilizes the OFFLINE_FLAG (new field) and LAST_SESSION_REFRESH fields.
As a result, the following queries are used to delete sessions:

  • Delete Online Session:

DELETE FROM OFFLINE_USER_SESSION WHERE REALM_ID = $1 AND OFFLINE_FLAG = 0 AND LAST_SESSION_REFRESH < $3;

  • Delete Offline Session:

DELETE FROM OFFLINE_USER_SESSION WHERE REALM_ID = $1 AND OFFLINE_FLAG = 1 AND LAST_SESSION_REFRESH < $3;

The issue arises when the Remember Me feature is enabled. In the online session scenario, LAST_SESSION_REFRESH is calculated based on the maximum value of either SSO Session Idle or SSO Session Idle Remember Me.
For example, if SSO Session Idle Remember Me is set to 120 days and SSO Session Idle is set to just 1 hour, the cleanup process will retain the online user session in the DB for 120 days, without deleting expired online sessions (no remember me).

Those transitioning to the persistent session feature and using the Remember Me option will see an increased number of entries in the OFFLINE_USER_SESSION and OFFLINE_CLIENT_SESSION tables.

So far, I haven’t found a workaround to clean up expired sessions for “normal” (non-remember-me) in the database, considering that the scheduled process waits until the SSO Session Idle Remember Me limit is reached.

1 Like