Skip to content

Conversation

@nikosdouvlis
Copy link
Member

@nikosdouvlis nikosdouvlis commented Jan 16, 2026

Why

When getToken() is called and the token is within the leeway window (15 seconds before expiration), it blocks while fetching a new token. This creates latency spikes for users actively using an app.

What

Implements a timer-based proactive refresh that triggers token refresh before the token enters the leeway zone:

Token lifetime: 60s
|--------43s--------|--2s--|--LEEWAY(10)+SYNC(5)--|
                    ^
            Timer fires here
            Triggers background refresh
  • Timer fires 2 seconds before the leeway period (at 43 seconds for 60-second tokens)
  • Background refresh creates a new cache entry
  • Concurrent getToken() calls await the same promise (no duplicate fetches)
  • If timer doesn't fire (e.g., background tab), we fall back to blocking (safe, current behavior)

Key changes

  • Add onExpiringSoon callback to TokenCacheEntry
  • Schedule proactive refresh timer when caching tokens
  • Pass callback in Session._getToken() and #hydrateCache()
  • Clean up refresh timers in all cache cleanup paths

Test plan

  • Existing tokenCache tests pass (30 tests)
  • Existing Session tests pass (45 tests)
  • Manual test: verify proactive refreshes in network tab
  • Add tests for proactive refresh behavior

Summary by CodeRabbit

  • New Features

    • Tokens are now proactively refreshed in the background before expiration, improving session reliability and reducing authentication interruptions.
  • Tests

    • Added comprehensive test coverage for proactive token refresh behavior, including timer management, token replacement, and edge cases around token expiration.

✏️ Tip: You can customize this high-level summary in your review settings.

@changeset-bot
Copy link

changeset-bot bot commented Jan 16, 2026

⚠️ No Changeset found

Latest commit: e2950bd

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@vercel
Copy link

vercel bot commented Jan 16, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
clerk-js-sandbox Ready Ready Preview, Comment Jan 16, 2026 9:33pm

Request Review

Adds a proactive refresh mechanism that triggers token refresh before
the token enters the leeway window. This prevents getToken() from
blocking when tokens are about to expire.

The timer fires 2 seconds before the leeway period (at 43 seconds for
60-second tokens), giving time for the background fetch to complete.
If the timer doesn't fire (e.g., background tab), we fall back to the
existing blocking behavior.

Key changes:
- Add onExpiringSoon callback to TokenCacheEntry
- Schedule proactive refresh timer when caching tokens
- Pass callback in Session._getToken() and #hydrateCache()
Why:
The timer-based proactive token refresh feature (0e812a2) needed test
coverage to verify getToken() behavior across all 6 timing scenarios.

What changed:
Added tests covering:
- Before timer fires (t < 43): returns cached token instantly
- After timer, fetch in progress (43 < t < 45): returns old token non-blocking
- After timer, fetch complete (43 < t < 45): returns new token from cache
- In leeway zone with completed fetch (t >= 45): returns new token
- In leeway zone with failed fetch (t >= 45): blocks and refetches
- Background tab scenario (timer didn't fire): safe fallback behavior
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 16, 2026

📝 Walkthrough

Walkthrough

This change implements proactive token refresh for session tokens. A new onExpiringSoon callback mechanism is added to TokenCacheEntry that triggers before tokens enter leeway, scheduling a refresh timer with a REFRESH_BUFFER delay. A private proactiveRefresh method handles background token fetching and cache updates. The implementation tracks refresh timeouts, manages timer cleanup across cache operations, and includes comprehensive test coverage validating timer scheduling, callback behavior, token resolution during refresh, and concurrent access scenarios.

🚥 Pre-merge checks | ✅ 3
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat(clerk-js): add timer-based proactive token refresh' directly and specifically describes the main change: implementing a timer-based mechanism for proactively refreshing tokens before they enter the leeway window.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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

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.

2 participants