Skip to content

Conversation

@bratsos
Copy link
Member

@bratsos bratsos commented Jan 14, 2026

Description

offline-demo.mp4

Checklist

  • pnpm test runs as expected.
  • pnpm build runs as expected.
  • (If applicable) JSDoc comments have been added or updated for any package exports
  • (If applicable) Documentation has been updated

Type of change

  • 🐛 Bug fix
  • 🌟 New feature
  • 🔨 Breaking change
  • 📖 Refactoring / dependency upgrade / documentation
  • other:

- Trigger background refresh when needsRefresh is true, without
  requiring refreshIfStale option. Guarantees cache revalidation
  without relying solely on the poller.

- Add #refreshTokenInBackground() that doesn't cache pending promise,
  allowing concurrent getToken() calls to return stale token while
  refresh is in progress.

- Track in-flight background refreshes to prevent duplicate requests.

- Rename DEFAULT_LEEWAY to BACKGROUND_REFRESH_THRESHOLD_IN_SECONDS
  with clear documentation about 15s minimum and rate limiting warning.

- Add comprehensive JSDoc for leewayInSeconds option explaining
  minimum value, default, and rate limiting considerations.
Add upgrade guide entries for:
- getToken `leewayInSeconds` minimum of 15 seconds
- stale-while-revalidate pattern for session tokens
- Test refreshIfStale: true forces synchronous refresh when token is stale
- Test refreshIfStale: true with fresh token returns cached value
- Test leewayInSeconds triggers earlier background refresh
- Test minimum 15s leeway enforcement
- Test no background refresh when token has sufficient TTL
- Rename option from leewayInSeconds to backgroundRefreshThreshold for clarity
- Lower minimum threshold from 15s to 5s (poller interval)
- Remove explicit refreshIfStale: false in AuthCookieService (default behavior)
- Update tests and upgrade documentation
@changeset-bot
Copy link

changeset-bot bot commented Jan 14, 2026

🦋 Changeset detected

Latest commit: 9de4869

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 21 packages
Name Type
@clerk/tanstack-react-start Major
@clerk/react-router Major
@clerk/clerk-js Major
@clerk/upgrade Major
@clerk/nextjs Major
@clerk/shared Major
@clerk/react Major
@clerk/nuxt Major
@clerk/vue Major
@clerk/chrome-extension Patch
@clerk/expo Patch
@clerk/agent-toolkit Patch
@clerk/astro Patch
@clerk/backend Patch
@clerk/expo-passkeys Patch
@clerk/express Patch
@clerk/fastify Patch
@clerk/localizations Patch
@clerk/msw Patch
@clerk/testing Patch
@clerk/ui Patch

Not sure what this means? Click here to learn what changesets are.

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

@vercel
Copy link

vercel bot commented Jan 14, 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 28, 2026 9:25pm

Request Review

@bratsos bratsos changed the base branch from main to alexbratsos/user-4045-make-gettoken-callable-outside-of-react January 14, 2026 17:37
Comment on lines 94 to 102
if (ClerkOfflineError.is(e)) {
throw e;
}

if (isNetworkError(e) || !isValidBrowserOnline()) {
throw new ClerkOfflineError('Network request failed', {
cause: e instanceof Error ? e : undefined,
});
}
Copy link
Member

Choose a reason for hiding this comment

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

Is this something we want to happen for all resources, or just the session resource?

Copy link
Member Author

Choose a reason for hiding this comment

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

I've change this since the last refactor, I've only kept the ClerkOfflineError exception only on session resource

@jacekradko
Copy link
Member

@bratsos I am concerned that this PR is going to conflict heavily with the stale-while-revalidate change: #7317

I think we will want to base this PR off feat/stale-while-revalidate-token and build on top of it. Some of the offline heuristics work well with SWR since we can return a cached token whenever possible and error only when we truly cannot fetch a new token

Base automatically changed from alexbratsos/user-4045-make-gettoken-callable-outside-of-react to main January 16, 2026 16:45
jacekradko and others added 8 commits January 26, 2026 19:14
Replace the stale-while-revalidate approach with a timer-based
proactive refresh mechanism. Instead of relying on getToken() calls
to trigger background refresh, we now schedule a timer when tokens
are cached that fires before the leeway period begins.

Key changes:
- Add onRefresh callback to TokenCacheEntry for proactive refresh
- Schedule refresh timer at (TTL - leeway - 2s) = 43s for 60s tokens
- Remove needsRefresh flag and refreshThreshold parameter from cache
- Remove backgroundRefreshThreshold and refreshIfStale from GetTokenOptions
- Update Session to pass onRefresh callback when caching tokens

Benefits:
- More consistent refresh regardless of getToken() call frequency
- Zero risk: if timer doesn't fire, poller catches it as fallback
- Fits naturally with existing cleanup timer pattern
BREAKING CHANGE: `getToken()` now throws `ClerkOfflineError` instead of
returning `null` when the client is offline. This makes it explicit that
the failure was due to network conditions, not authentication state.
@bratsos bratsos force-pushed the alexbratsos/user-4063-improve-gettoken-offline-handling branch from b6350c6 to 640e362 Compare January 28, 2026 21:14
@bratsos bratsos changed the title [WIP] feat(clerk-js): Improve getToken offline handling feat(clerk-js): Improve getToken offline handling Jan 28, 2026
@bratsos bratsos requested a review from jacekradko January 28, 2026 21:15
@bratsos bratsos changed the base branch from main to feat/stale-while-revalidate-token January 28, 2026 21:16
@bratsos bratsos marked this pull request as ready for review January 28, 2026 21:16
Comment on lines +2 to +10
'@clerk/tanstack-react-start': major
'@clerk/react-router': major
'@clerk/clerk-js': major
'@clerk/upgrade': major
'@clerk/nextjs': major
'@clerk/shared': major
'@clerk/react': major
'@clerk/nuxt': major
'@clerk/vue': major
Copy link
Member Author

Choose a reason for hiding this comment

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

I'm not sure if this should be a major change in all sdks 🤔

Base automatically changed from feat/stale-while-revalidate-token to main January 30, 2026 02:56
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.

3 participants