Skip to main content

I am seeing an increase in people being prompted to purchase after they have already subscribed


Forum|alt.badge.img+3

I am using the following code in RN to determine if a user is subscribed:

        const customerInfo = await Purchases.getCustomerInfo();

        const isActive = Object.entries(customerInfo.entitlements.active).length > 0;

 

I have received multiple emails recently about people saying they are subscribed but being prompted to subscribe again. No code has changed in this regard. I’ve received emails from iOS and Android users.

 

Is there a better check or a bug in the SDK?  The above code is run when the app boots and sets a global session state. It seems to have worked well for a year+.

This post has been closed for comments

2 replies

guilherme
RevenueCat Staff
Forum|alt.badge.img+2
  • RevenueCat Staff
  • 40 replies
  • April 29, 2025

Hey ​@MichaelP,

This usually relates to how the RevenueCat SDK caches subscription information (CustomerInfo). Below is a breakdown of how caching works, and the best practices for keeping it up to date reliably across app sessions.

CustomerInfo Caching

The SDK caches CustomerInfo locally on device to reduce network overhead and improve performance. This cache is automatically refreshed when:

  • the app moves to the foregroung
  • you explicitly call getCustomerInfo()
  • a purchase or restore is completed

However, if a user’s subscription status changes while the app is completely closed (e.g., a trial converts or a renewal occurs), the cached data will not reflect that change until one of the above triggers occurs. To this, some suggested best practises into keeping it accurate/up to date are:

1. Use a CustomerInfo Listener

The most reliable way to stay in sync during an app session is to listen for updates using addCustomerInfoUpdateListener (docs here). This ensures your app state reacts to any updates without manual polling or re-fetching. An example in code could be:

// React Native example
useEffect(() => {
  const listener = Purchases.addCustomerInfoUpdateListener((customerInfo) => {
    const hasAccess = customerInfo.entitlements.active["premium_access"] != null;
    setHasAccess(hasAccess);
  });

  return () => listener.remove();
}, []);


2. Fetch CustomerInfo at Key Times

In addition to the listener, you should call getCustomerInfo() manually:

  • on app launch or after login - which seems to be your case
  • when navigating to a paywalled feature
  • after any account change (login/logout)

This ensures your access logic is based on the most recent available data, especially after long periods in the background. Like so:

const customerInfo = await Purchases.getCustomerInfo();
const hasAccess = customerInfo.entitlements.active["premium_access"] != null;


3. Enable Server-to-Server Notifications
If you're concerned about subscription changes happening outside of the app (e.g., upgrades, renewals, cancellations), consider setting up Server-to-Server (S2S) notifications. These ensure RevenueCat’s backend stays up-to-date with Apple and Google’s stores, even when the app isn’t running.

Once the backend is in sync, any subsequent call to getCustomerInfo() will reflect the correct state.

Docs: Platform Server Notifications

 

Optional: Forcing a Cache Refresh 

If you need to guarantee a fresh subscription state due to a critical flow or after a state mismatch, you can manually invalidate the SDK’s cache and fetch updated data:

await Purchases.invalidateCustomerInfoCache();
const customerInfo = await Purchases.getCustomerInfo();

This method works, but should be used sparingly to avoid unnecessary network requests. For example, only after an external event or when debugging desync issues.

Some extra context around caching, which might be good to be aware/consider:

  • the cache persists across app launches
  • foregrounded apps auto-refresh every 5 minutes
  • backgrounded apps refresh after ~25 hours
  • any purchase or restore triggers an immediate update

Docs: Caching CustomerInfo

Let me know how these changes help you and feel free to reach out if you have any more questions!

Best,
Gui


Forum|alt.badge.img+3
  • Author
  • New Member
  • 1 reply
  • April 29, 2025

Thank you! Great information.


Cookie policy

We use cookies to enhance and personalize your experience. If you accept you agree to our full cookie policy. Learn more about our cookies.

 
Cookie settings