Skip to content

Throttle SSO session activity touch to cut write load - #4257

Open
madurangasiriwardena wants to merge 1 commit into
thunder-id:mainfrom
madurangasiriwardena:session-activity-touch-throttling
Open

Throttle SSO session activity touch to cut write load#4257
madurangasiriwardena wants to merge 1 commit into
thunder-id:mainfrom
madurangasiriwardena:session-activity-touch-throttling

Conversation

@madurangasiriwardena

@madurangasiriwardena madurangasiriwardena commented Jul 22, 2026

Copy link
Copy Markdown
Member

Purpose

Every SSO session reuse ran an unconditional UPDATE on SSO_SESSION to slide the idle deadline and refresh LAST_ACTIVE_AT. On the hot reuse path this was the dominant write load, and on PostgreSQL the main source of dead tuples (MVCC bloat) on the session table.

This PR throttles that activity refresh so a burst of reuses within a short window costs a single write instead of one per request, and makes the throttle window operator-configurable.

Approach

  • Throttle in LoadCheckpoint (internal/flow/session/service.go): the idle-slide UPDATE is skipped when the last persisted activity refresh is within the activity-refresh window (now - LastActiveAt < ActivityRefresh). The persisted idle deadline then lags real activity by at most that interval.
  • Participant upsert left unthrottled: recordParticipant also registers an application joining a session for the first time, so throttling it could drop a genuine first-join record. Only the session idle-slide write is throttled.
  • A zero/stale LastActiveAt yields a large elapsed time, so first refreshes and long-idle reuse write exactly as before.
  • Configurable window: added the session.activityRefreshIntervalSeconds server-config key, threaded through NewTimeouts and both call sites (cmd/server/servicemanager.go, internal/flow/flowexec/init.go).

Configuring the activity-refresh interval

session.activityRefreshIntervalSeconds (seconds) lives in the existing session server-config section, alongside idleTimeoutSeconds and absoluteTimeoutSeconds. It can be overridden two ways:

  1. Declaratively — a server-config document at config/resources/server_configs/session.yaml:
    resource_type: server_config
    name: session
    value:
    idleTimeoutSeconds: 1800
    absoluteTimeoutSeconds: 28800
    activityRefreshIntervalSeconds: 60
  2. At runtime — via the server-config API (the writable layer). Merge overlays the writable value over the declarative one per field, so a positive activityRefreshIntervalSeconds from the API overrides the declarative/default value.

Related Issues

  • N/A

Related PRs

  • N/A

Checklist

  • Followed the contribution guidelines.
  • Manual test round performed and verified.
  • Documentation provided. (Add links if there are any)
    • Ran Vale and fixed all errors and warnings
  • Tests provided. (Add links if there are any)
    • Unit Tests
    • Integration Tests
  • Breaking changes. (Fill if applicable)
    • Breaking changes section filled.
    • breaking change label added.

Security checks

  • Followed secure coding standards in WSO2 Secure Coding Guidelines
  • Confirmed that this PR doesn't commit any keys, passwords, tokens, usernames, or other secrets.

Summary by CodeRabbit

  • New Features
    • Added a configurable activity-based session refresh interval (activityRefreshIntervalSeconds) for SSO session timeouts.
    • Idle expiration now slides on activity refreshes, respecting the configured minimum interval.
  • Bug Fixes
    • Strengthened validation for the refresh interval: rejects negative/overflowing values and enforces the relationship to idle timeout, including correct behavior with defaults and config merges.
  • Performance
    • Reduced unnecessary session database writes by throttling activity persistence when activity occurs within the refresh window, while keeping absolute expiration and participant tracking behavior intact.

@coderabbitai

coderabbitai Bot commented Jul 22, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 3d650471-2e25-4f0b-8f92-a0f20ae73664

📥 Commits

Reviewing files that changed from the base of the PR and between 3bdf80e and 0287b54.

📒 Files selected for processing (9)
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/flowexec/init.go
  • backend/internal/flow/session/config.go
  • backend/internal/flow/session/config_test.go
  • backend/internal/flow/session/init.go
  • backend/internal/flow/session/service.go
  • backend/internal/flow/session/service_test.go
  • backend/internal/flow/session/state.go
  • backend/internal/flow/session/state_test.go

📝 Walkthrough

Walkthrough

Session timeout configuration now includes an activity refresh interval. Initialization passes the configured value into timeout construction, validation and merging handle it, and checkpoint loading throttles activity persistence while retaining participant recording behavior.

Changes

Session activity refresh

Layer / File(s) Summary
Timeout configuration and validation
backend/internal/flow/session/state.go, backend/internal/flow/session/config.go, backend/internal/flow/session/*_test.go
Adds activity-refresh timeout resolution, validation, writable-config merging, initialization fallback, and coverage for defaults and overrides.
Timeout construction wiring
backend/cmd/server/servicemanager.go, backend/internal/flow/flowexec/init.go
Passes the configured activity refresh interval into session.NewTimeouts and threads related configuration services through initialization.
Checkpoint activity refresh behavior
backend/internal/flow/session/service.go, backend/internal/flow/session/service_test.go
Skips recent activity persistence within the refresh window and persists LastActiveAt and IdleExpiresAt after the window expires, with tests for both paths.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Suggested reviewers: indeewari, thamindudilshan, rajithacharith, darshanasbg

Sequence Diagram(s)

sequenceDiagram
  participant LoadCheckpoint
  participant SessionTimeouts
  participant SessionStore
  LoadCheckpoint->>SessionTimeouts: Read ActivityRefresh
  LoadCheckpoint->>LoadCheckpoint: Compare elapsed time since LastActiveAt
  alt Refresh window elapsed
    LoadCheckpoint->>SessionStore: Persist LastActiveAt and IdleExpiresAt
  else Within refresh window
    LoadCheckpoint->>SessionStore: Record joining participant best-effort
  end
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: throttling SSO session activity refreshes to reduce write load.
Description check ✅ Passed The description follows the template with Purpose, Approach, related links, checklist, and security sections, and it explains the implementation well.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@madurangasiriwardena
madurangasiriwardena force-pushed the session-activity-touch-throttling branch from 19e4b9d to 1934037 Compare July 22, 2026 13:19
@madurangasiriwardena
madurangasiriwardena force-pushed the session-activity-touch-throttling branch 3 times, most recently from 248a10e to ee1d378 Compare July 23, 2026 04:45
@codecov

codecov Bot commented Jul 23, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 86.66667% with 4 lines in your changes missing coverage. Please review.

Files with missing lines Patch % Lines
backend/internal/flow/session/init.go 0.00% 1 Missing and 1 partial ⚠️
backend/internal/flow/session/service.go 60.00% 1 Missing and 1 partial ⚠️

📢 Thoughts on this report? Let us know!

@madurangasiriwardena
madurangasiriwardena force-pushed the session-activity-touch-throttling branch from ee1d378 to 8efe0b9 Compare July 24, 2026 09:26
@madurangasiriwardena
madurangasiriwardena marked this pull request as ready for review July 24, 2026 09:28

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/internal/flow/session/config.go`:
- Around line 32-37: Update the session configuration documentation in
docs/content/apis.mdx to document session.activityRefreshIntervalSeconds,
including its 60-second default, requirement to remain below idleTimeoutSeconds,
and throttled activity-refresh behavior. Update or create the relevant session
configuration guide under docs/content/guides/ to explain reduced database
writes and how the setting affects idle expiry.

In `@backend/internal/flow/session/state.go`:
- Around line 54-58: Validate ActivityRefreshIntervalSeconds against the maximum
representable time.Duration before NewTimeouts invokes activityRefreshInterval,
rejecting positive values whose seconds-to-duration conversion would overflow.
Update the relevant Config.Validate or NewTimeouts validation path while
preserving the default behavior for non-positive values and normal positive
intervals.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 8860d4ef-f4f9-4211-ac2e-760be3f7e149

📥 Commits

Reviewing files that changed from the base of the PR and between 00091d3 and 8efe0b9.

📒 Files selected for processing (8)
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/flowexec/init.go
  • backend/internal/flow/session/config.go
  • backend/internal/flow/session/config_test.go
  • backend/internal/flow/session/service.go
  • backend/internal/flow/session/service_test.go
  • backend/internal/flow/session/state.go
  • backend/internal/flow/session/state_test.go

Comment on lines +32 to +37
// ActivityRefreshIntervalSeconds is the minimum spacing between persisted activity refreshes: a
// session reuse within this window of the last persisted activity refresh skips the idle-slide
// write, cutting write load on the hot path. It is honored as configured and must be less than
// idleTimeoutSeconds (enforced by Validate), so an active session is never skipped past its idle
// deadline.
ActivityRefreshIntervalSeconds int64 `json:"activityRefreshIntervalSeconds" yaml:"activityRefreshIntervalSeconds"`

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.

📐 Maintainability & Code Quality | 🟠 Major | ⚡ Quick win

🔴 Documentation Required
This PR introduces user-facing changes that are not covered by documentation updates under docs/.
Please update the relevant documentation before merging.

Missing documentation:

  • session.activityRefreshIntervalSeconds: Document the default of 60 seconds, its requirement to remain below idleTimeoutSeconds, and its throttled session activity behavior in the server-config API reference at docs/content/apis.mdx.
  • Session activity refresh behavior: Update or create the relevant session configuration guide under docs/content/guides/ to explain the database-write throttling and idle-expiry effect.

As per path instructions, configuration options require consolidated documentation coverage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@backend/internal/flow/session/config.go` around lines 32 - 37, Update the
session configuration documentation in docs/content/apis.mdx to document
session.activityRefreshIntervalSeconds, including its 60-second default,
requirement to remain below idleTimeoutSeconds, and throttled activity-refresh
behavior. Update or create the relevant session configuration guide under
docs/content/guides/ to explain reduced database writes and how the setting
affects idle expiry.

Source: Path instructions

Comment thread backend/internal/flow/session/state.go Outdated
Comment thread backend/internal/flow/session/state.go Outdated
// used when the deployment does not configure session.activityRefreshIntervalSeconds. Within this
// window after the last persisted activity refresh, the activity refresh (the idle-slide UPDATE) is
// skipped to cut write amplification on the hot session-reuse path.
const DefaultActivityRefreshInterval = 60 * time.Second

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Shall we make this private if not required to be accessed outside session package?

@madurangasiriwardena
madurangasiriwardena force-pushed the session-activity-touch-throttling branch 2 times, most recently from 5fa6bec to 3bdf80e Compare July 27, 2026 05:57

@coderabbitai coderabbitai Bot 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.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@backend/internal/flow/session/state.go`:
- Around line 45-55: Update session.Initialize in init.go to apply the default
ActivityRefresh whenever timeouts.ActivityRefresh is <= 0, alongside the
existing Idle and Absolute fallbacks. Use the established default timeout
configuration so zero-valued and legacy keyed Timeouts receive the intended
refresh interval.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 034a5340-406a-49f9-8e20-0b2ba8c3fcd9

📥 Commits

Reviewing files that changed from the base of the PR and between 5fa6bec and 3bdf80e.

📒 Files selected for processing (8)
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/flowexec/init.go
  • backend/internal/flow/session/config.go
  • backend/internal/flow/session/config_test.go
  • backend/internal/flow/session/service.go
  • backend/internal/flow/session/service_test.go
  • backend/internal/flow/session/state.go
  • backend/internal/flow/session/state_test.go
🚧 Files skipped from review as they are similar to previous changes (7)
  • backend/internal/flow/flowexec/init.go
  • backend/internal/flow/session/config_test.go
  • backend/internal/flow/session/service.go
  • backend/cmd/server/servicemanager.go
  • backend/internal/flow/session/state_test.go
  • backend/internal/flow/session/config.go
  • backend/internal/flow/session/service_test.go

Comment thread backend/internal/flow/session/state.go
@madurangasiriwardena
madurangasiriwardena force-pushed the session-activity-touch-throttling branch from 3bdf80e to 8ee4944 Compare July 27, 2026 06:07
Every SSO session reuse ran an unconditional UPDATE to slide the idle
deadline and refresh last-active on SSO_SESSION. On the hot reuse path this
was the dominant write load and, on PostgreSQL, the main source of dead
tuples on the session table.

Throttle it in LoadCheckpoint: skip the idle-slide UPDATE when the last
persisted activity refresh is within the activity-refresh window. The
persisted idle deadline then lags real activity by at most that interval. The
participant upsert is left unthrottled because it also registers an
application joining the session for the first time.

The interval is operator-configurable via the new
session.activityRefreshIntervalSeconds server-config key (seconds), falling
back to a built-in 60s default. It is honored as configured; Validate
requires it to be less than idleTimeoutSeconds so an active session is never
skipped past its idle deadline.
@madurangasiriwardena
madurangasiriwardena force-pushed the session-activity-touch-throttling branch from 8ee4944 to 0287b54 Compare July 30, 2026 04:07
@madurangasiriwardena madurangasiriwardena added the trigger-pr-builder Add when the PR is ready for CI; starts the PR Builder for this and all later pushes label Jul 30, 2026
@ThaminduDilshan
ThaminduDilshan added this pull request to the merge queue Jul 30, 2026
@github-merge-queue
github-merge-queue Bot removed this pull request from the merge queue due to a conflict with the base branch Jul 30, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

trigger-pr-builder Add when the PR is ready for CI; starts the PR Builder for this and all later pushes Type/Improvement

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants