Check Cache-Control on per-user API responses
Request an endpoint that returns the signed-in user's data and read its Cache-Control header. Per-user responses, especially those received after login or tied to a cookie session, should carry private or no-store, not public or s-maxage.
curl -s -o /dev/null -D - -H "Authorization: Bearer $TOKEN" https://YOUR_APP/api/me | grep -i cache-control
Docs: developer.mozilla.org →
Find query keys that leave out the user
Search for query keys on per-user data that hold a fixed string and nothing else. If the query function reads the current user, the key needs the user's ID as well.
grep -rnE "queryKey: \[['\"][a-zA-Z]+['\"]\]" src
Docs: tanstack.com →
Stop caches storing per-user responses
private keeps a response out of shared caches but lets the browser store it. no-store tells every cache, private or shared, not to store the response, which also covers account switches in the same browser.
Cache-Control: no-store
Docs: developer.mozilla.org →
Put the user ID in every per-user query key
Add the user ID to the key so each account gets its own cache entry and a new user triggers a new fetch.
const { data } = useQuery({
queryKey: ['profile', userId],
queryFn: () => fetchProfile(userId),
})
Docs: tanstack.com →
Clear browser storage when SIGNED_OUT fires
Listen for the SIGNED_OUT event in onAuthStateChange and remove what the app stored for the previous user. Supabase documents the callback as safe without an async function.
supabase.auth.onAuthStateChange((event) => {
if (event === 'SIGNED_OUT') {
[window.localStorage, window.sessionStorage].forEach((storage) => {
Object.entries(storage).forEach(([key]) => storage.removeItem(key))
})
}
})
Docs: supabase.com →
Send Clear-Site-Data on the sign-out response
Add the header to the response that confirms sign-out so the browser drops its HTTP cache and DOM storage for your origin. Each directive needs double quotes.
Clear-Site-Data: "cache", "storage"
Docs: developer.mozilla.org →