All articles
Mobile Dev

Scaling Mobile Monetization in 2025: Google Play Billing v7 & Expo Router Architecture

Kibet Brian
Kibet Brian
November 18, 2025
Scaling Mobile Monetization in 2025: Google Play Billing v7 & Expo Router Architecture

Scaling Mobile Monetization in 2025: Google Play Billing v7 & Expo Router Architecture

Monetizing mobile applications on Android and iOS requires navigating strict platform guidelines, asynchronous payment lifecycles, and resilient backend entitlement engines. With Google Play Billing Library v7 enforcement throughout 2025 and 2026, developers must handle complex subscription state machines including grace periods, account holds, and instant upgrade/downgrade prorations.

Here is how we built and scaled mobile subscription architecture for production applications like Sagent and PeNote.

1. Native Billing Integration with Expo Plugin Architecture

Modern React Native apps built with Expo utilize Config Plugins to maintain clean, native code generation without manual native folder edits:

// app.config.ts - Expo Billing Plugin Config
export default ({ config }: ConfigContext): ExpoConfig => ({
  ...config,
  name: "Sagent Pro",
  slug: "sagent-app",
  plugins: [
    [
      "react-native-iap",
      {
        paymentProvider: "Both",
      },
    ],
  ],
});

2. Server-Side Real-Time Developer Notifications (RTDN)

Client-side receipt verification is vulnerable to man-in-the-middle tampering. All subscription status changes must be validated asynchronously via Google Cloud Pub/Sub webhooks:

// Webhook Endpoint for Google Play RTDN Notifications
export async function POST(req: Request) {
  const body = await req.json();
  const messageData = Buffer.from(body.message.data, "base64").toString("utf-8");
  const notification = JSON.parse(messageData);

  if (notification.subscriptionNotification) {
    const { subscriptionId, purchaseToken, notificationType } = notification.subscriptionNotification;
    
    // Process notification types: RENEWED, CANCELLED, IN_GRACE_PERIOD
    await handleSubscriptionEvent(subscriptionId, purchaseToken, notificationType);
  }

  return new Response("OK", { status: 200 });
}

3. Resilience Against Grace Periods & Account Holds

Subscriptions do not simply flip from active to expired. A robust entitlement state engine must handle intermediate payment failure states:

  • Active: Full feature access enabled.
  • In Grace Period (7-14 Days): Payment failed, but access remains enabled while Google retries the user's payment method.
  • Account Hold (Up to 30 Days): Access suspended, but subscription remains active pending payment recovery.
  • Expired: Access revoked; prompt user with one-click win-back subscription flow.
export function computeUserEntitlementStatus(sub: SubscriptionRecord): EntitlementState {
  if (sub.status === 'ACTIVE' || sub.status === 'GRACE_PERIOD') {
    return { isProUser: true, statusMessage: sub.status === 'GRACE_PERIOD' ? 'Update Payment Method' : 'Active' };
  }
  return { isProUser: false, statusMessage: 'Subscription Inactive' };
}

4. Local Entitlement Caching & Offline Support

Users expecting offline access (e.g. note-taking apps or offline template managers) shouldn't be blocked when airplane mode is enabled. Store entitlement tokens in encrypted device storage (Expo SecureStore) with an expiration TTL (Time to Live) of 72 hours.

Key Learnings

In-app subscriptions in 2025 demand server-authoritative entitlement verification paired with responsive, offline-aware client state management. Implementing robust RTDN webhooks and handling grace periods gracefully reduces churn by up to 18% and delivers a premium user experience.