---
title: "Understanding Google Play’s subscription price changes: a complete guide"
description: "You will cover how to manage subscription price changes—covering opt-in vs. opt-out models, notification requirements, implementation details, and how RevenueCat helps handle the process smoothly for both new and existing subscribers."
language: "en"
publishedAt: "2026-01-21T01:49:31Z"
updatedAt: "2026-01-21T01:49:31Z"
authors:
  - name: "Jaewoong Eum"
    url: "https://www.revenuecat.com/blog/author/jaewoong-eum"
category: "Engineering"
categoryUrl: "https://www.revenuecat.com/blog/engineering"
readingTime: 14
canonical: "https://www.revenuecat.com/blog/engineering/google-play-price-change"
---

# Understanding Google Play’s subscription price changes: a complete guide

You will cover how to manage subscription price changes—covering opt-in vs. opt-out models, notification requirements, implementation details, and how RevenueCat helps handle the process smoothly for both new and existing subscribers.

## Table of contents

- [How price changes affect different subscriber groups](#how-price-changes-affect-different-subscriber-groups)
  - [New subscribers](#new-subscribers)
  - [Existing subscribers: the legacy price cohort](#existing-subscribers-the-legacy-price-cohort)
- [Ending a legacy price cohort](#ending-a-legacy-price-cohort)
  - [Using the migration API](#using-the-migration-api)
- [Price decrease flow](#price-decrease-flow)
  - [How price decreases work](#how-price-decreases-work)
  - [Handling price decreases in your app](#handling-price-decreases-in-your-app)
- [Price increase flow: opt-in increases](#price-increase-flow-opt-in-increases)
  - [The opt-in timeline](#the-opt-in-timeline)
  - [User acceptance requirement](#user-acceptance-requirement)
  - [Handling opt-in increases in your app](#handling-opt-in-increases-in-your-app)
  - [Communicating value during price increases](#communicating-value-during-price-increases)
- [Price increase flow: opt-out increases](#price-increase-flow-opt-out-increases)
  - [Eligibility requirements](#eligibility-requirements)
  - [Opt-out timeline](#opt-out-timeline)
  - [Handling opt-out increases](#handling-opt-out-increases)
- [In-app notification requirements](#in-app-notification-requirements)
  - [Mandatory notification surfaces](#mandatory-notification-surfaces)
  - [Notification timing](#notification-timing)
- [Handling overlapping price changes](#handling-overlapping-price-changes)
  - [The cancellation and replacement flow](#the-cancellation-and-replacement-flow)
  - [Tracking price change status](#tracking-price-change-status)
- [Recovering from accidental price changes](#recovering-from-accidental-price-changes)
  - [Reverting opt-in increases](#reverting-opt-in-increases)
  - [Reverting opt-out increases](#reverting-opt-out-increases)
  - [Reverting price decreases](#reverting-price-decreases)
- [Installment subscriptions and price changes](#installment-subscriptions-and-price-changes)
- [Testing price changes](#testing-price-changes)
  - [Using license testers](#using-license-testers)
  - [Play Billing Lab](#play-billing-lab)
  - [Audit trail](#audit-trail)
- [How RevenueCat simplifies price change management](#how-revenuecat-simplifies-price-change-management)
  - [Automatic state tracking](#automatic-state-tracking)
  - [Management URL for user actions](#management-url-for-user-actions)
  - [Cross-platform consistency](#cross-platform-consistency)
  - [Webhooks for server side handling](#webhooks-for-server-side-handling)
  - [Analytics for price change impact](#analytics-for-price-change-impact)
  - [Best practices with RevenueCat](#best-practices-with-revenuecat)
- [Best practices for subscription price changes](#best-practices-for-subscription-price-changes)
  - [Plan your communication strategy](#plan-your-communication-strategy)
  - [Use regional rollouts](#use-regional-rollouts)
  - [Monitor acceptance rates](#monitor-acceptance-rates)
  - [Provide alternatives](#provide-alternatives)
  - [Handle the transition gracefully in your app](#handle-the-transition-gracefully-in-your-app)
- [Conclusion](#conclusion)

Subscription pricing is rarely static. Market conditions change, costs fluctuate, and business strategies evolve. At some point, you will likely need to adjust your subscription prices, whether increasing them to reflect added value or decreasing them to attract more users. However, changing subscription prices on Google Play is not as simple as updating a number in a dashboard.

Price changes affect existing subscribers differently than new customers, require specific notification flows, and must be handled carefully to maintain user trust and comply with Google Play’s policies. Luckily, this article will explain how subscription price changes work on Google Play in-depth. We’ll cover:

- Mechanics of changing prices for both new and existing subscribers
- Differences between opt-in and opt-out price increases
- Notification requirements and timelines
- Implementation details (with a walk through example)
- How RevenueCat can help manage price changes gracefully across your subscriber base
## **How price changes affect different subscriber groups**

When you modify a subscription price in the Google Play Console or via the API, the change doesn’t affect all users in the same way. Here’s how Google Play handles new subscribers and existing subscribers differently:

### **New subscribers**

For new purchases, price changes take effect relatively quickly, typically within a few hours of making the change. Once the new price is active, anyone who initiates a new subscription purchase will see and pay the updated price. No special handling is required for this group; they simply see the current price when they reach the purchase screen.

### **Existing subscribers: the legacy price cohort**

Existing subscribers are a different matter entirely. By default, when you change a subscription price, current subscribers are placed into what Google calls a **legacy price cohort**. These users continue paying their original price at each renewal, completely unaffected by the price change. This default behavior protects users from unexpected billing changes and gives you control over when and how to migrate them to new pricing.

This legacy cohort mechanism means changing a price in the Play Console **does not automatically change what existing subscribers pay**. You must explicitly choose to migrate subscribers to the new price.

## **Ending a legacy price cohort**

When you decide to move existing subscribers from their legacy price to a new price, you use the price migration API. This initiates either a price increase or price decrease flow, depending on whether the new price is higher or lower than what users currently pay.

### **Using the migration API**

To migrate subscribers to a new price, you call the [monetization.subscriptions.basePlans.migratePrices](https://developers.google.com/android-publisher/api-ref/rest/v3/monetization.subscriptions.basePlans/migratePrices) endpoint on your backend side:

```kotlin
\/\/ Backend service for initiating price migration
class PriceMigrationService(
    private val androidPublisher: AndroidPublisher
) {
    fun migrateSubscribersToNewPrice(
        packageName: String,
        productId: String,
        basePlanId: String,
        regions: List<String>,
        newPriceAmountMicros: Long,
        currencyCode: String
    ) {
        val regionalConfigs = regions.map { regionCode ->
            RegionalPriceMigrationConfig().apply {
                this.regionCode = regionCode
                this.priceIncreaseType = "OPT_IN" \/\/ or "OPT_OUT" if eligible
                this.oldestAllowedPriceVersionTime = null \/\/ migrate all legacy cohorts
            }
        }

        val request = MigratePricesRequest().apply {
            this.regionalPriceMigrationConfigs = regionalConfigs
        }

        androidPublisher
            .monetization()
            .subscriptions()
            .basePlans()
            .migratePrices(packageName, productId, basePlanId, request)
            .execute()
    }
}
```

The migration is specific to each region, allowing you to roll out price changes gradually across different markets or handle regional pricing differences independently.

## **Price decrease flow**

When the new price is lower than what users currently pay, the migration process is straightforward and easy for users. Price decreases are automatically applied without requiring explicit user acceptance.

### **How price decreases work**

When you migrate subscribers to a lower price, Google Play sends email notifications informing users of the price decrease. Users then begin paying the lower price at their next renewal, and no user action is required since the decrease happens automatically.

There is one timing nuance to be aware of: Google Play may authorize payment up to 48 hours before renewal (or up to five days in India and Brazil). If a user’s payment was already authorized at the higher price before the decrease was applied, they will pay the higher price for that renewal but will receive the lower price on subsequent renewals.

### **Handling price decreases in your app**

From an implementation perspective, price decreases require minimal handling. You may want to communicate the good news to users:

```kotlin
class PriceChangeManager(
    private val backendApi: BackendApi
) {
    suspend fun checkForPriceChanges(userId: String): PriceChangeInfo? {
        val subscriptionStatus = backendApi.getSubscriptionStatus(userId)
        val priceChange = subscriptionStatus.pendingPriceChange ?: return null

        return when {
            priceChange.newPriceMicros < priceChange.currentPriceMicros -> {
                PriceChangeInfo.Decrease(
                    currentPrice = formatPrice(priceChange.currentPriceMicros),
                    newPrice = formatPrice(priceChange.newPriceMicros),
                    effectiveDate = priceChange.effectiveDate
                )
            }
            else -> {
                \/\/ Handle price increase (covered in next section)
                handlePriceIncrease(priceChange)
            }
        }
    }
}

\/\/ In your UI layer
fun showPriceDecreaseNotification(info: PriceChangeInfo.Decrease) {
    showBanner(
        title = "Good news!",
        message = "Your subscription price is decreasing from ${info.currentPrice} " +
            "to ${info.newPrice} starting ${formatDate(info.effectiveDate)}."
    )
}
```

Price decreases are generally positive events for users, so your primary concern is ensuring they are aware of the change rather than managing any acceptance flow.

## **Price increase flow: opt-in increases**

Price increases are more complex because they require user awareness and, in most cases, explicit acceptance. The default method for price increases is the **opt-in** flow, where users must explicitly agree to the new price before being charged.

### **The opt-in timeline**

The opt-in price increase flow follows a specific timeline with distinct phases:

| **Phase** | **Duration** | **What Happens** |
| --- | --- | --- |
| Freeze period | Days 1 to 7 | Google Play sends no notifications; developer can notify users |
| Notification period | Days 8 to 37 | Google Play sends email and push notifications |
| Effective date | Day 37 onwards | Price increase takes effect; charged at next renewal |

The seven day freeze period at the beginning is intentional. It gives you the opportunity to notify users through your own channels before Google Play’s automated notifications begin. This allows you to control the messaging and potentially explain the value users receive for the increased price.

### **User acceptance requirement**

For opt-in price increases, users must explicitly accept the new price. They do this through the Play Store subscription management screen, where they see a dialog explaining the price change and can either accept or decline.

If a user doesn’t accept the price increase before their first renewal at the new price, their subscription is automatically canceled. They retain access until the end of their current billing period, but the subscription will not renew.

### **Handling opt-in increases in your app**

Your app should detect pending price increases and guide users through the acceptance process:

```kotlin
class OptInPriceIncreaseManager(
    private val billingClient: BillingClient,
    private val backendApi: BackendApi
) {
    sealed class PriceIncreaseState {
        object None : PriceIncreaseState()
        data class Pending(
            val currentPrice: String,
            val newPrice: String,
            val effectiveDate: Instant,
            val inFreezePeriod: Boolean
        ) : PriceIncreaseState()
        object Accepted : PriceIncreaseState()
        object Declined : PriceIncreaseState()
    }

    suspend fun checkPriceIncreaseStatus(userId: String): PriceIncreaseState {
        val subscriptionStatus = backendApi.getSubscriptionStatus(userId)
        val priceChange = subscriptionStatus.pendingPriceChange

        if (priceChange == null || priceChange.newPriceMicros <= priceChange.currentPriceMicros) {
            return PriceIncreaseState.None
        }

        return when (priceChange.state) {
            "OUTSTANDING" -> {
                val freezePeriodEnd = priceChange.initiatedAt.plus(Duration.ofDays(7))
                PriceIncreaseState.Pending(
                    currentPrice = formatPrice(priceChange.currentPriceMicros),
                    newPrice = formatPrice(priceChange.newPriceMicros),
                    effectiveDate = priceChange.effectiveDate,
                    inFreezePeriod = Instant.now().isBefore(freezePeriodEnd)
                )
            }
            "CONFIRMED" -> PriceIncreaseState.Accepted
            "CANCELED" -> PriceIncreaseState.Declined
            else -> PriceIncreaseState.None
        }
    }

    fun showPriceIncreaseUI(
        activity: Activity,
        state: PriceIncreaseState.Pending
    ) {
        if (state.inFreezePeriod) {
            \/\/ During freeze period, show your own messaging
            showCustomPriceIncreaseDialog(
                currentPrice = state.currentPrice,
                newPrice = state.newPrice,
                effectiveDate = state.effectiveDate,
                onAcceptClick = { openPlayStoreSubscriptionSettings(activity) }
            )
        } else {
            \/\/ After freeze period, can also use Google's in app messaging
            showInAppMessage(activity)
        }
    }

    private fun showInAppMessage(activity: Activity) {
        val params = InAppMessageParams.newBuilder()
            .addInAppMessageCategoryToShow(
                InAppMessageParams.InAppMessageCategoryId.SUBSCRIPTION_PRICE_CHANGE
            )
            .build()

        billingClient.showInAppMessages(activity, params) { result ->
            \/\/ Handle the result
            when (result.responseCode) {
                InAppMessageResult.InAppMessageResponseCode.NO_ACTION_NEEDED -> {
                    \/\/ No price change message needed or user already responded
                }
                InAppMessageResult.InAppMessageResponseCode.SUBSCRIPTION_STATUS_UPDATED -> {
                    \/\/ User interacted with the message - refresh subscription status
                    refreshSubscriptionStatus()
                }
            }
        }
    }

    private fun openPlayStoreSubscriptionSettings(activity: Activity) {
        val intent = Intent(Intent.ACTION_VIEW).apply {
            data = Uri.parse(
                "<https:\/\/play.google.com\/store\/account\/subscriptions>"
            )
            setPackage("com.android.vending")
        }
        activity.startActivity(intent)
    }
}
```

### **Communicating value during price increases**

The freeze period is your opportunity to communicate directly with users about why the price is increasing. Effective communication can significantly improve acceptance rates:

```kotlin
fun showCustomPriceIncreaseDialog(
    currentPrice: String,
    newPrice: String,
    effectiveDate: Instant,
    onAcceptClick: () -> Unit
) {
    showDialog(
        title = "Subscription Update",
        message = """
            Starting ${formatDate(effectiveDate)}, your subscription will change
            from $currentPrice to $newPrice per month.

            Since you subscribed, we've added:
            \u2022 Advanced analytics dashboard
            \u2022 Offline mode for all content
            \u2022 Priority customer support
            \u2022 And 15+ other features

            To continue enjoying these features, please confirm the new price
            in your Play Store subscription settings.
        """.trimIndent(),
        positiveButton = "Review in Play Store" to onAcceptClick,
        negativeButton = "Maybe Later" to { \/* dismiss *\/ }
    )
}
```

## **Price increase flow: opt-out increases**

In certain regions and under specific conditions, Google Play allows **opt-out** price increases. With opt-out increases, users are notified of the price change but are automatically charged the new price unless they explicitly cancel or change their plan.

### **Eligibility requirements**

Opt-out price increases are not universally available. Eligibility depends on several factors including regional availability (only certain countries support opt-out increases), frequency limits on how often you can use them, maximum percentage or absolute amount restrictions per country, and additional developer eligibility requirements. Because of these restrictions, opt-out increases should be considered a supplementary option rather than your primary approach to price changes.

### **Opt-out timeline**

The opt-out timeline differs from opt-in increases:

| **Aspect** | **Opt In** | **opt-out** |
| --- | --- | --- |
| Freeze period | 7 days | None |
| Notification period | 30 days | 30 or 60 days (varies by country) |
| User action required | Must accept | Can cancel to avoid |
| Default behavior | Subscription cancels | New price charged |

The notification period for opt-out varies by country. Some require 30 days notice, while others require 60 days. Google Play handles these regional requirements automatically when you initiate an opt-out migration.

### **Handling opt-out increases**

From an implementation perspective, opt-out increases are simpler because users do not need to take action to continue their subscription:

```kotlin
fun handleOptOutPriceIncrease(priceChange: PriceChangeInfo) {
    \/\/ For opt-out increases, the state will be "CONFIRMED" rather than "OUTSTANDING"
    \/\/ Users will be charged the new price automatically unless they cancel

    showNotification(
        title = "Subscription Price Update",
        message = "Starting ${formatDate(priceChange.effectiveDate)}, " +
            "your subscription will be ${priceChange.newPrice}\/month. " +
            "No action needed to continue your subscription."
    )
}
```

However, you should still communicate clearly with users about the upcoming change, even though their action is not required.

## **In-app notification requirements**

Regardless of whether you use opt-in or opt-out price increases, Google Play requires you to display in-app notices about price changes. This requirement applies across all device types where your app runs.

### **Mandatory notification surfaces**

You must show price change notifications on mobile devices (phones and tablets), Android TV, and other streaming devices. The only exception is watches, where in-app notification is recommended but not strictly required due to the limited screen real estate.

### **Notification timing**

For opt-in increases, the recommended approach is to show your own custom messaging explaining the value proposition during the freeze period (days one to seven), then continue showing reminders and use Google’s In App Messaging API after the freeze period ends (days eight onwards).

```kotlin
class PriceChangeNotificationManager(
    private val billingClient: BillingClient
) {
    fun showPriceChangeNotificationIfNeeded(
        activity: Activity,
        priceIncreaseState: PriceIncreaseState
    ) {
        when (priceIncreaseState) {
            is PriceIncreaseState.Pending -> {
                \/\/ Always show some form of notification for pending increases
                if (priceIncreaseState.inFreezePeriod) {
                    showCustomNotificationBanner(activity, priceIncreaseState)
                } else {
                    \/\/ Use Google's in app messaging
                    showGoogleInAppMessage(activity)
                }
            }
            else -> {
                \/\/ No notification needed
            }
        }
    }

    private fun showCustomNotificationBanner(
        activity: Activity,
        state: PriceIncreaseState.Pending
    ) {
        \/\/ Show a subtle banner at the top of the screen
        val banner = PriceChangeBanner(activity).apply {
            setMessage(
                "Your subscription price will change to ${state.newPrice} " +
                "on ${formatDate(state.effectiveDate)}. Tap to review."
            )
            setOnClickListener {
                openPriceChangeDetails(activity, state)
            }
        }
        banner.show()
    }

    private fun showGoogleInAppMessage(activity: Activity) {
        val params = InAppMessageParams.newBuilder()
            .addInAppMessageCategoryToShow(
                InAppMessageParams.InAppMessageCategoryId.SUBSCRIPTION_PRICE_CHANGE
            )
            .build()

        billingClient.showInAppMessages(activity, params) { \/* handle result *\/ }
    }
}
```

## **Handling overlapping price changes**

What happens if you initiate a new price change while a previous one is still pending? Google Play handles this by canceling the previous price change and applying the new one.

### **The cancellation and replacement flow**

When overlapping price changes occur, the old price migration is marked as CANCELED and you receive a SUBSCRIPTION_PRICE_CHANGE_UPDATED Real-Time Developer Notification (RTDN). The new price migration then takes effect, and users only need to respond to the latest price change. This behavior prevents users from being forced to accept multiple sequential price increases, which would create a poor user experience.

### **Tracking price change status**

Your backend should process RTDN notifications to track price change status:

```kotlin
\/\/ Backend notification handler
class PriceChangeNotificationHandler(
    private val subscriptionRepository: SubscriptionRepository,
    private val playDeveloperApi: AndroidPublisher
) {
    fun handlePriceChangeNotification(notification: DeveloperNotification) {
        val purchaseToken = notification.subscriptionNotification.purchaseToken

        when (notification.subscriptionNotification.notificationType) {
            NotificationType.SUBSCRIPTION_PRICE_CHANGE_UPDATED -> {
                \/\/ Query the current state of the price change
                val subscription = playDeveloperApi
                    .purchases()
                    .subscriptionsv2()
                    .get(packageName, purchaseToken)
                    .execute()

                val priceChangeState = subscription.lineItems[0]
                    .autoRenewingPlan
                    ?.priceChangeDetails

                if (priceChangeState != null) {
                    subscriptionRepository.updatePriceChangeStatus(
                        purchaseToken = purchaseToken,
                        state = priceChangeState.priceChangeState,
                        newPriceMicros = priceChangeState.newPrice?.priceMicros,
                        expectedNewPriceChargeTime = priceChangeState.expectedNewPriceChargeTime
                    )

                    \/\/ Notify app layer to update UI if needed
                    notifyPriceChangeUpdated(purchaseToken, priceChangeState)
                }
            }
        }
    }
}
```

## **Recovering from accidental price changes**

Mistakes happen. If you accidentally change a price or initiate a migration you did not intend, the recovery process depends on the type of change and how much time has passed.

### **Reverting opt-in increases**

For opt-in price increases, the timing of your revert matters significantly. If you revert within seven days (the freeze period), users will not have received any notifications from Google Play, so the change is essentially invisible to them. After seven days, reverting will cancel the price change for users who have not yet been charged at the new price, but some users may have already received notifications, which could cause confusion.

### **Reverting opt-out increases**

For opt-out price increases, reverting to the original price cancels the increase for users who have not yet been charged. Keep in mind the authorization timing. Users whose payment was already authorized (up to five days before renewal in some regions) may still be charged.

### **Reverting price decreases**

If you need to cancel a price decrease and return to the original higher price, start by reverting to the original price in the Play Console and choosing whether the increase should be opt-in or opt-out. The timing relative to user renewals determines the outcome: if the time between revert and user renewal is greater than the notification window (30 to 60 days depending on country), users will pay the original price at their next renewal. If the time is less than the notification window, users will be charged the lower price once, then go through the standard price increase notification flow.

## **Installment subscriptions and price changes**

If your subscription uses installment plans (where users commit to a certain number of payments), price changes behave differently.

For installment subscriptions, price changes only apply at the end of the active commitment period. You cannot change the price for users in the middle of an installment, and the new price takes effect at the first renewal after the commitment ends. For example, if a user is on a 12 month installment plan followed by monthly auto renewal, any price change you make will only take effect after their 12 month commitment completes and they move to the monthly renewal phase.

## **Testing price changes**

Before rolling out price changes to your production subscriber base, you should thoroughly test the flows using Google Play’s testing tools.

### **Using license testers**

License testers can receive price change notifications without affecting real subscribers. Configure license testers in the Play Console and use them to verify notification delivery and timing, in app messaging display, acceptance and decline flows, and state transitions in your backend.

### **Play Billing Lab**

Google provides the [Play Billing Lab app](https://play.google.com/store/apps/details?id=com.google.android.apps.play.billingtestcompanion) for testing billing scenarios. Use it to simulate price change scenarios and verify your app handles each state correctly.

### **Audit trail**

The Play Console maintains a change log of all price modifications. Use this to review when prices were updated, who initiated the changes, and which regions were affected. This audit trail is invaluable for investigating issues or reviewing the history of accidental changes.

## **How RevenueCat simplifies price change management**

Managing price changes across a large subscriber base involves significant complexity. This includes tracking migration status for each user, processing RTDN notifications, displaying appropriate in-app messaging, and handling edge cases. RevenueCat abstracts away much of this complexity while providing additional tools for managing price changes effectively.

### **Automatic state tracking**

RevenueCat processes Google Play’s RTDN notifications on your behalf, maintaining up to date subscription state including pending price changes. Instead of building infrastructure to receive and process notifications, you simply query RevenueCat for the current customer state:

```kotlin
fun checkForPriceChanges() {
    Purchases.sharedInstance.getCustomerInfoWith { customerInfo ->
        val entitlement = customerInfo.entitlements["premium"]

        \/\/ RevenueCat's CustomerInfo reflects current subscription state
        \/\/ including any pending price changes processed from RTDN

        if (entitlement?.isActive == true) {
            \/\/ Check for billing issues that might indicate price change problems
            entitlement.billingIssueDetectedAt?.let { issueDate ->
                showBillingRecoveryUI(customerInfo.managementURL)
            }
        }
    }
}
```

### **Management URL for user actions**

RevenueCat’s CustomerInfo includes a [managementURL](https://www.revenuecat.com/docs/subscription-guidance/managing-subscriptions#using-the-managementurl-to-help-customers-cancel-a-subscription) property that provides a direct link to Google Play’s subscription management screen. This is where users can accept or decline price changes:

```kotlin
fun guideToPriceChangeAcceptance(customerInfo: CustomerInfo) {
    val managementUrl = customerInfo.managementURL

    showDialog(
        title = "Action Required",
        message = "Please review the upcoming changes to your subscription.",
        positiveButton = "Open Settings" to {
            openUrl(managementUrl)
        }
    )
}
```

### **Cross-platform consistency**

For apps that span multiple platforms, RevenueCat ensures consistent subscription state across Android, iOS, and other platforms. If a user accepts a price change on one device, the updated status is reflected across all their devices without additional implementation.

### **Webhooks for server side handling**

RevenueCat provides webhooks that notify your server of subscription events in a normalized format. This is simpler than processing raw RTDN notifications and includes events related to price changes:

```kotlin
\/\/ Your webhook handler
fun handleRevenueCatWebhook(event: WebhookEvent) {
    when (event.type) {
        "RENEWAL" -> {
            \/\/ Renewal completed - check if price changed
            val transaction = event.transaction
            if (transaction.priceInPurchasedCurrency != previousPrice) {
                \/\/ Price change took effect
                updateUserPricing(event.appUserId, transaction.priceInPurchasedCurrency)
            }
        }
        "CANCELLATION" -> {
            \/\/ User canceled, might be due to price change rejection
            val reason = event.cancellationReason
            if (reason == "PRICE_INCREASE") {
                \/\/ Track churn related to price changes
                analytics.trackPriceChangeChurn(event.appUserId)
            }
        }
    }
}
```

### **Analytics for price change impact**

[RevenueCat’s Chart](https://www.revenuecat.com/docs/dashboard-and-metrics/charts) provides analytics that help you understand the impact of price changes, including churn rates correlated with price change timing, conversion rates for subscribers who received price increase notifications, and revenue impact analysis before and after price changes. These insights help you make informed decisions about pricing strategy and identify the optimal timing and communication approach for future price changes.

### **Best practices with RevenueCat**

When using RevenueCat for price change management, focus on proactive communication by using customer attributes to identify users with pending price changes and send targeted communications during the freeze period. Monitor key metrics such as the conversion rate from price increase notification to acceptance and the churn rate among affected users. Always provide users with an easy path to the Play Store subscription settings via the management URL. Finally, leverage RevenueCat’s normalized data to handle edge cases gracefully, such as users who change plans during a pending price increase.

## **Best practices for subscription price changes**

Based on the mechanics we have covered, here are key practices to implement for successful price changes:

### **Plan your communication strategy**

Before initiating a price change, plan how you will communicate with affected users. Prepare messaging that explains the value users receive, decide whether to use the freeze period for custom outreach, and consider offering alternatives such as annual plans or grandfathered pricing for users sensitive to price changes.

### **Use regional rollouts**

If you are increasing prices globally, consider rolling out changes region by region. Test in smaller markets first to gauge response, adjust messaging based on early feedback, and allow time to address issues before they affect your largest markets.

### **Monitor acceptance rates**

Track how many users accept opt-in price increases versus letting their subscriptions cancel:

```kotlin
class PriceChangeAnalytics(
    private val analytics: AnalyticsService
) {
    fun trackPriceChangeOutcome(
        userId: String,
        originalPrice: Long,
        newPrice: Long,
        outcome: PriceChangeOutcome
    ) {
        analytics.track(
            event = "price_change_outcome",
            properties = mapOf(
                "user_id" to userId,
                "original_price_micros" to originalPrice,
                "new_price_micros" to newPrice,
                "increase_percentage" to calculatePercentage(originalPrice, newPrice),
                "outcome" to outcome.name
            )
        )
    }
}

enum class PriceChangeOutcome {
    ACCEPTED,
    DECLINED,
    SUBSCRIPTION_CANCELED,
    NO_RESPONSE_BEFORE_DEADLINE
}
```

If acceptance rates are lower than expected, you may need to adjust your communication strategy or reconsider the price increase amount.

### **Provide alternatives**

Users who are unwilling to pay the higher price may be willing to continue at a different tier. Consider offering a downgrade path to a plan with lower pricing, providing an annual option at a discounted effective monthly rate, or creating a ‘lite’ tier that retains users who would otherwise churn.

### **Handle the transition gracefully in your app**

Ensure your app gracefully handles all states during a price change. Users with pending price increases should see clear messaging, users who decline should not lose access immediately, and the transition between prices should be seamless for users who accept.

## **Conclusion**

Subscription price changes on Google Play involve a carefully orchestrated process designed to protect users while giving developers flexibility. The key concepts to understand are the legacy price cohort that shields existing subscribers from automatic price changes, the distinction between opt-in and opt-out price increases and their respective timelines, the notification requirements that apply across device types, and the regional variations that affect timing and eligibility.

For price decreases, the process is straightforward. Users automatically receive the lower price at their next renewal. For price increases, the default opt-in flow requires explicit user acceptance, with a seven day freeze period followed by 30 days of Google Play notifications before the effective date.

Implementing price changes directly requires processing RTDN notifications, maintaining subscription state on your backend, and building UI to guide users through the acceptance process. RevenueCat simplifies this by handling notification processing automatically and providing normalized data, analytics, and the management URL for user actions, so you can focus on your business and more important work.

Whatever approach you take, successful price changes require clear communication with users about the value they receive. The freeze period is your opportunity to control the narrative before automated notifications begin. Use it wisely, and you can maintain user trust while adjusting your pricing to reflect the value your app delivers.For complete documentation on subscription price changes, refer to the [official Android Developer documentation](https://developer.android.com/google/play/billing/price-changes) and [RevenueCat’s subscription management guide](https://www.revenuecat.com/docs/subscription-guidance/managing-subscriptions).

---

## Related posts

- [Understanding Google Play subscription proration: a developer’s guide](https://www.revenuecat.com/blog/engineering/google-proration)
- [Building animated custom Paywalls in Jetpack Compose](https://www.revenuecat.com/blog/engineering/custom-paywalls-compose)
- [Turn Your App into Revenue: Building Paywalls in Android With Jetpack Compose](https://www.revenuecat.com/blog/engineering/build-paywalls-compose)
