Skip to content

When expiring sessions, check if sessions exist to avoid a lot of extra queries - #55014

Draft
ahus1 wants to merge 4 commits into
keycloak:mainfrom
ahus1:is-54886-skip-expiration-empty-realm
Draft

ahus1 wants to merge 4 commits into
keycloak:mainfrom
ahus1:is-54886-skip-expiration-empty-realm

Conversation

@ahus1

@ahus1 ahus1 commented Nov 10, 2026 •

Copy link
Copy Markdown
Member

Closes #54886

Each expiration run first looks for a single session of the realm and type with a one-row index lookup, and only runs the per-bucket queries if one exists. The lookup is a prefix seek on the existing expiration index, so no schema change is needed and the fix can be backported.

Decision: nothing is remembered between runs. An earlier version recorded the time a realm was found empty and skipped it until the idle timeout passed. That saved the probe query, but it depended on the wall clock, on node-local state in a shared singleton, and on the assumption that new sessions never carry a timestamp older than the observation. It was fragile under time offsets and clock changes, and it needed extra guards and tests. The probe costs one query per realm and type per run instead of about 259, which resolves the issue without that risk. A per-bucket high-water mark is tracked in #55012.

Decision: the probe runs in its own short transaction. The expiration runs in an outer transaction while the deletes use inner transactions, and a read in the outer one could hold shared locks under strict isolation levels that the deletes then wait for.

Assumption: for offline sessions the probe does not filter by REMEMBER_ME, as that column can be true, false or NULL there. The skipped migration of the remember-me flag only concerns regular sessions, which are probed separately.

Assumption: the integration test uses Hibernate statistics, which are shared with the periodic expiration task, so it asserts on query kinds and retries up to three times. It fails without the fix.

…ra queries

Closes keycloak#54886

Signed-off-by: Alexander Schwartz <alexander.schwartz@ibm.com>
ahus1 and others added 2 commits November 10, 2026 21:04
Closes keycloak#54886

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Alexander Schwartz <alexander.schwartz@ibm.com>
…ty realms

Closes keycloak#54886

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Alexander Schwartz <alexander.schwartz@ibm.com>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The test’s getUserSession() null check does not prove the expired database row was deleted; it should use UserSessionPersisterProvider.loadUserSession(..., false) to verify persistence cleanup.

1 open issue
What changed in this PR

Reduces persistent-session expiration overhead for empty realms, addressing #54886 without schema changes or state carried between runs.

Changes:

  • Adds a one-row existence query scoped by realm and session type.
  • Skips bucketed expiration queries when no matching sessions exist, using separate short transactions for probes.
  • Adds integration tests for empty-realm query behavior and expiration after a realm gains a session.
File Description
tests/​base/​src/​test/​java/​org/​keycloak/​tests/​model/​UserSessionExpirationQueryCountTest.java Adds query-behavior and session-expiration regression tests.
model/​jpa/​src/​main/​java/​org/​keycloak/​models/​jpa/​session/​PersistentUserSessionEntity.java Defines the session-existence named query.
model/​jpa/​src/​main/​java/​org/​keycloak/​models/​jpa/​session/​JpaUserSessionPersisterProvider.java Probes for sessions before running bucketed expiration.

Review effort: Balanced

@ahus1
ahus1 requested review from ruchikajha95 and removed request for ruchikajha95 November 12, 2026 11:47
Updated user session retrieval method in test.

Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Signed-off-by: Alexander Schwartz <alexander.schwartz@gmx.net>

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

No active review issues block approval of the empty-realm session-expiration optimization.

No open issues 🎉

1 resolved since last review

Review effort: Balanced

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Session expiration task issues ~37x more SELECTs per realm since 26.8.0 (64 session buckets), causing constant DB load with many realms

2 participants