[GH-ISSUE #6987] Session update not syncing secondary storage mappings #10691

Closed
opened 2026-04-13 06:58:41 -05:00 by GiteaMirror · 6 comments
Owner

Originally created by @Ridhim-RR on GitHub (Dec 24, 2025).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/6987

Originally assigned to: @bytaesu on GitHub.

Title: updateSession doesn’t persist updated data to secondary storage

Summary

When using secondaryStorage with storeSessionInDatabase: false, the updateSession function merges new session fields in memory but never writes them back to secondary storage. This results in stale session data being read after refreshes — even though the route sets a new cookie and reports success.

Expected Behavior

  • The updated session should be persisted back to secondary storage, refreshing:
  • The actual session record (with merged updates)
  • TTL / expiration in the secondary store
  • Active sessions list (if supported)

This ensures subsequent reads return the refreshed session, consistent with the cookie data and route response

Originally created by @Ridhim-RR on GitHub (Dec 24, 2025). Original GitHub issue: https://github.com/better-auth/better-auth/issues/6987 Originally assigned to: @bytaesu on GitHub. **Title: updateSession doesn’t persist updated data to secondary storage** **Summary** When using secondaryStorage with storeSessionInDatabase: false, the updateSession function merges new session fields in memory but never writes them back to secondary storage. This results in stale session data being read after refreshes — even though the route sets a new cookie and reports success. **Expected Behavior** - The updated session should be persisted back to secondary storage, refreshing: - The actual session record (with merged updates) - TTL / expiration in the secondary store - Active sessions list (if supported) This ensures subsequent reads return the refreshed session, consistent with the cookie data and route response
GiteaMirror added the lockedbug labels 2026-04-13 06:58:41 -05:00
Author
Owner

@better-auth-agent[bot] commented on GitHub (Dec 24, 2025):

The issue you're experiencing with the updateSession function appears to be related to the behavior of secondary storage not persisting updated session fields back to the database when storeSessionInDatabase is set to false. This could result in stale session data being returned after a refresh, as you've described.

Next Steps:

  1. Check Implementation:
    Ensure that your implementation correctly initializes and persists session fields in secondary storage. Changes made to updateSession should also trigger persistence operations to update session fields in both memory and secondary storage.

  2. Review Configuration:
    If you're using a secondary storage implementation like Redis, confirm that the methods (set, get, delete) are correctly integrated and the TTL settings are appropriately configured.

  3. Look for Open Issues/PRs:
    There are discussions regarding updating session data correctly in secondary storage. For instance, PRs about session attribute persistence and secondary storage updates may provide insight into fixing this issue [1], [8].

If you require further assistance, don't hesitate to tag the better-auth team members, Beka and Max, with @bekacru and @ping__ so they can assist you further.

Is there a particular part of your implementation that you're unsure about?

If you need more help, tag @better-auth-agent in a comment so I can respond.

DiagramDiscordGitHub

Diagram Join Star

<!-- gh-comment-id:3690241898 --> @better-auth-agent[bot] commented on GitHub (Dec 24, 2025): The issue you're experiencing with the `updateSession` function appears to be related to the behavior of secondary storage not persisting updated session fields back to the database when `storeSessionInDatabase` is set to `false`. This could result in stale session data being returned after a refresh, as you've described. ### Next Steps: 1. **Check Implementation**: Ensure that your implementation correctly initializes and persists session fields in secondary storage. Changes made to `updateSession` should also trigger persistence operations to update session fields in both memory and secondary storage. 2. **Review Configuration**: If you're using a secondary storage implementation like Redis, confirm that the methods (`set`, `get`, `delete`) are correctly integrated and the TTL settings are appropriately configured. 3. **Look for Open Issues/PRs**: There are discussions regarding updating session data correctly in secondary storage. For instance, PRs about session attribute persistence and secondary storage updates may provide insight into fixing this issue [[1]](https://github.com/better-auth/better-auth/pull/5804), [[8]](https://github.com/better-auth/better-auth/pull/3000). If you require further assistance, don't hesitate to tag the better-auth team members, Beka and Max, with @bekacru and @ping__ so they can assist you further. Is there a particular part of your implementation that you're unsure about? _If you need more help, tag @better-auth-agent in a comment so I can respond._ <!-- bot:webhook reply v1 --> [Diagram](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) • [Discord](https://discord.gg/fG2XXEuQX3) • [GitHub](https://github.com/Skyvern-AI/Skyvern) [![Diagram](https://img.shields.io/badge/Diagram-2b3137?style=flat-square)](https://repodiagrams.s3.eu-north-1.amazonaws.com/skyvern_ultra_detailed_interactive.html) [![Join](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&style=flat-square)](https://discord.gg/fG2XXEuQX3) [![Star](https://img.shields.io/badge/star-181717?logo=github&logoColor=white&style=flat-square)](https://github.com/Skyvern-AI/Skyvern)
Author
Owner

@dosubot[bot] commented on GitHub (Dec 24, 2025):

You are correct: when using secondaryStorage with storeSessionInDatabase: false, updateSession merges new session fields in memory but does not persist the updated session back to secondary storage. This causes stale session data to be served after refreshes, even if the cookie and route response show the updated data. The session in secondary storage is only updated during authentication events (like sign-in or token refresh), not when updateSession or user profile changes occur, which is a known limitation and has been acknowledged by maintainers (source).

To work around this, you can manually update or invalidate sessions in secondary storage after making updates. For example, after a profile or session update, use a custom hook or logic to delete or refresh all sessions for the user in secondary storage, forcing new sessions to be created with up-to-date data (example). Here’s a sample pattern:

// Example: manually update all user sessions in secondary storage (e.g., Redis)
export async function updateUserSessionInKv(updatedUser) {
  const kv = hubKV(); // or your Redis client
  const sessionList = await kv.get(`_auth:active-sessions-${updatedUser.id}`);
  if (!sessionList || !Array.isArray(sessionList)) return;
  await Promise.all(sessionList.map(async (session) => {
    const sessionData = await kv.get(`_auth:${session.token}`);
    if (!sessionData) return;
    await kv.set(`_auth:${session.token}`, {
      ...sessionData,
      user: updatedUser,
    });
  }));
}

Also, make sure your secondaryStorage implementation correctly serializes and deserializes session data (using JSON.stringify/parse) to avoid missing or stale fields (source).

There is no evidence that this limitation has been fixed as of the latest code and issues reviewed. If you need session updates to be reflected immediately in secondary storage, a manual update or invalidation step is currently required.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:3690246269 --> @dosubot[bot] commented on GitHub (Dec 24, 2025): <!-- Answer --> You are correct: when using secondaryStorage with storeSessionInDatabase: false, updateSession merges new session fields in memory but does not persist the updated session back to secondary storage. This causes stale session data to be served after refreshes, even if the cookie and route response show the updated data. The session in secondary storage is only updated during authentication events (like sign-in or token refresh), not when updateSession or user profile changes occur, which is a known limitation and has been acknowledged by maintainers [(source)](https://github.com/better-auth/better-auth/issues/4721). To work around this, you can manually update or invalidate sessions in secondary storage after making updates. For example, after a profile or session update, use a custom hook or logic to delete or refresh all sessions for the user in secondary storage, forcing new sessions to be created with up-to-date data [(example)](https://github.com/better-auth/better-auth/issues/4721#issuecomment-3469336842). Here’s a sample pattern: ```ts // Example: manually update all user sessions in secondary storage (e.g., Redis) export async function updateUserSessionInKv(updatedUser) { const kv = hubKV(); // or your Redis client const sessionList = await kv.get(`_auth:active-sessions-${updatedUser.id}`); if (!sessionList || !Array.isArray(sessionList)) return; await Promise.all(sessionList.map(async (session) => { const sessionData = await kv.get(`_auth:${session.token}`); if (!sessionData) return; await kv.set(`_auth:${session.token}`, { ...sessionData, user: updatedUser, }); })); } ``` Also, make sure your secondaryStorage implementation correctly serializes and deserializes session data (using JSON.stringify/parse) to avoid missing or stale fields [(source)](https://github.com/better-auth/better-auth/issues/5687#issuecomment-3469336842). There is no evidence that this limitation has been fixed as of the latest code and issues reviewed. If you need session updates to be reflected immediately in secondary storage, a manual update or invalidation step is currently required. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/f92f907b-16a2-4024-8e08-7f6bd479df86?feedback_type=great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/f92f907b-16a2-4024-8e08-7f6bd479df86?feedback_type=irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/f92f907b-16a2-4024-8e08-7f6bd479df86?feedback_type=incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/f92f907b-16a2-4024-8e08-7f6bd479df86?feedback_type=too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/f92f907b-16a2-4024-8e08-7f6bd479df86?feedback_type=hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/f92f907b-16a2-4024-8e08-7f6bd479df86?feedback_type=bug_report) | [Other](https://app.dosu.dev/response-feedback/f92f907b-16a2-4024-8e08-7f6bd479df86?feedback_type=other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=You%20are%20correct%3A%20when%20using%20secondaryStorage%20with%20storeSessionInDatabase%3A%20false%2C%20updateSession%20merges%20new%20session%20fields%20in%20memory%20but%20does%20not%20persist%20the%20updated%20session%20back%20to%20secondary%20storage.%20This%20causes%20stale%20session%20data%20to%20be%20served%20after%20refreshes%2C%20even%20if%20the%20cookie%20and%20route%20response%20show%20the%20updated%20data.%20The%20session%20in%20secondary%20storage%20is%20only%20updated%20during%20authentication%20events%20%28like%20sign-in%20or%20token%20refresh%29%2C%20not%20when%20updateSession%20or%20user%20profile%20changes%20occur%2C%20which%20is%20a%20known%20limitation%20and%20has%20been%20acknowledged%20by%20maintainers%20%5B%28source%29%5D%28https%3A//github.com/better-auth/better-auth/issues/4721%29.%0A%0ATo%20work%20around%20this%2C%20you%20can%20manually%20update%20or%20invalidate%20sessions%20in%20secondary%20storage%20after%20making%20updates.%20For%20example%2C%20after%20a%20profile%20or%20session%20update%2C%20use%20a%20custom%20hook%20or%20logic%20to%20delete%20or%20refresh%20all%20sessions%20for%20the%20user%20in%20secondary%20storage%2C%20forcing%20new%20sessions%20to%20be%20created%20with%20up-to-date%20data%20%5B%28example%29%5D%28https%3A//github.com/better-auth/better-auth/issues/4721%23issuecomment-3469336842%29.%20Here%E2%80%99s%20a%20sample%20pattern%3A%0A%0A%60%60%60ts%0A//%20Example%3A%20manually%20update%20all%20user%20sessions%20in%20secondary%20storage%20%28e.g.%2C%20Redis%29%0Aexport%20async%20function%20updateUserSessionInKv%28updatedUser%29%20%7B%0A%20%20const%20kv%20%3D%20hubKV%28%29%3B%20//%20or%20your%20Redis%20client%0A%20%20const%20sessionList%20%3D%20await%20kv.get%28%60_auth%3Aactive-sessions-%24%7BupdatedUser.id%7D%60%29%3B%0A%20%20if%20%28%21sessionList%20%7C%7C%20%21Array.isArray%28sessionList%29%29%20return%3B%0A%20%20await%20Promise.all%28sessionList.map%28async%20%28session%29%20%3D%3E%20%7B%0A%20%20%20%20const%20sessionData%20%3D%20await%20kv.get%28%60_auth%3A%24%7Bsession.token%7D%60%29%3B%0A%20%20%20%20if%20%28%21sessionData%29%20return%3B%0A%20%20%20%20await%20kv.set%28%60_auth%3A%24%7Bsession.token%7D%60%2C%20%7B%0A%20%20%20%20%20%20...sessionData%2C%0A%20%20%20%20%20%20user%3A%20updatedUser%2C%0A%20%20%20%20%7D%29%3B%0A%20%20%7D%29%29%3B%0A%7D%0A%60%60%60%0A%0AAlso%2C%20make%20sure%20your%20secondaryStorage%20implementation%20correctly%20serializes%20and%20deserializes%20session%20data%20%28using%20JSON.stringify/parse%29%20to%20avoid%20missing%20or%20stale%20fields%20%5B%28source%29%5D%28https%3A//github.com/better-auth/better-auth/issues/5687%23issuecomment-3469336842%29.%0A%0AThere%20is%20no%20evidence%20that%20this%20limitation%20has%20been%20fixed%20as%20of%20the%20latest%20code%20and%20issues%20reviewed.%20If%20you%20need%20session%20updates%20to%20be%20reflected%20immediately%20in%20secondary%20storage%2C%20a%20manual%20update%20or%20invalidation%20step%20is%20currently%20required.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/6987)
Author
Owner

@ethan-huo commented on GitHub (Dec 25, 2025):

rel: https://github.com/better-auth/better-auth/issues/6993

<!-- gh-comment-id:3690970395 --> @ethan-huo commented on GitHub (Dec 25, 2025): rel: https://github.com/better-auth/better-auth/issues/6993
Author
Owner

@dvanmali commented on GitHub (Dec 26, 2025):

Currently OAuth Provider requires sessions to be stored on the database. Pushed patch #7000 to ensure setting storeSessionInDatabase: true until KV supports session ids.

<!-- gh-comment-id:3692375563 --> @dvanmali commented on GitHub (Dec 26, 2025): Currently OAuth Provider requires sessions to be stored on the database. Pushed patch #7000 to ensure setting `storeSessionInDatabase: true` until KV supports session ids.
Author
Owner

@Ridhim-RR commented on GitHub (Dec 26, 2025):

@dvanmali
Here the issue was updateSession function as it is not updating the secondaryStorage.

updateSession: async (
			sessionToken: string,
			session: Partial<Session> & Record<string, any>,
		) => {
			const updatedSession = await updateWithHooks<Session>(
				session,
				[{ field: "token", value: sessionToken }],
				"session",
				secondaryStorage
					? {
							async fn(data) {
								const currentSession = await secondaryStorage.get(sessionToken);
								let updatedSession: Session | null = null;
								if (currentSession) {
									const parsedSession = safeJSONParse<{
										session: Session;
										user: User;
									}>(currentSession);
									if (!parsedSession) return null;
									updatedSession = {
										...parsedSession.session,
										...data,
									};
									return updatedSession;
								} else {
									return null;
								}
							},
							executeMainFn: options.session?.storeSessionInDatabase,
						}
					: undefined,
			);
			return updatedSession;

As you can see the current implementation is returning the updateSession but it is not updating the secondaryStorage

<!-- gh-comment-id:3692764150 --> @Ridhim-RR commented on GitHub (Dec 26, 2025): @dvanmali Here the issue was updateSession function as it is not updating the secondaryStorage. ``` updateSession: async ( sessionToken: string, session: Partial<Session> & Record<string, any>, ) => { const updatedSession = await updateWithHooks<Session>( session, [{ field: "token", value: sessionToken }], "session", secondaryStorage ? { async fn(data) { const currentSession = await secondaryStorage.get(sessionToken); let updatedSession: Session | null = null; if (currentSession) { const parsedSession = safeJSONParse<{ session: Session; user: User; }>(currentSession); if (!parsedSession) return null; updatedSession = { ...parsedSession.session, ...data, }; return updatedSession; } else { return null; } }, executeMainFn: options.session?.storeSessionInDatabase, } : undefined, ); return updatedSession; ``` As you can see the current implementation is returning the updateSession but it is not updating the secondaryStorage
Author
Owner

@bytaesu commented on GitHub (Dec 27, 2025):

Hi @Ridhim-RR, I'm looking into this!

<!-- gh-comment-id:3693865430 --> @bytaesu commented on GitHub (Dec 27, 2025): Hi @Ridhim-RR, I'm looking into this!
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#10691