-
Handling Downgrades with APPLY_ON_NEXT_BILLING_CYCLE
When a client subscribes to the Plus plan and later decides to downgrade to the Basic plan, the downgrade remains in a pending state until the next billing date because of APPLY_ON_NEXT_BILLING_CYCLE. At that time, Shopify sends a webhook with the new Basic plan as “Active.”However, what happens if the client changes their mind before the next billing date and either:
- Wants to upgrade instead of downgrading?
- Decides to stay on the current plan (cancel the downgrade)?
Since Shopify does not provide a way to cancel a pending downgrade, this can create a situation where multiple active subscriptions exist. Shopify only cancels previous subscriptions when there is a single active one, but if multiple subscriptions are pending or active, it does not automatically resolve them.
How can we properly manage this scenario to ensure there is only one active subscription at a time?
2. Production Behavior of APPLY_ON_NEXT_BILLING_CYCLE
In development, after subscribing to a new plan (even with 15 days remaining on the current one), Shopify immediately sends:
- A Cancel webhook for the previous plan
- An Active webhook for the new plan
Does this behavior remain the same in production? Or do these webhooks only trigger on the next billing date?
If they only trigger on the next billing date, how can we confirm whether the payment was successful or if the pending subscription will simply expire without being charged?
mutation AppSubscriptionCreate {
appSubscriptionCreate(
name: "PLUSBilling"
replacementBehavior: APPLY_ON_NEXT_BILLING_CYCLE
lineItems: {
plan: {
appRecurringPricingDetails: {
interval: EVERY_30_DAYS
price: { amount: "151", currencyCode: USD }
discount: { }
}
}
}
test: true
returnUrl: "https://google.com"
)
So in the subscriptions there could be many Active subscription plans, this is not what i want. And if the client has the confirmation link of previous PENDING page, they can still click on paid which will creates multiple Active plans
{
"createdAt": "2025-02-26T03:29:38Z",
"currentPeriodEnd": null,
"id": "gid://shopify/AppSubscription/34265301281",
"name": "PLUSBilling",
"returnUrl": "https://google.com/",
"status": "PENDING",
"test": true,
"trialDays": 0
},
{
"createdAt": "2025-02-26T03:29:39Z",
"currentPeriodEnd": null,
"id": "gid://shopify/AppSubscription/34265334049",
"name": "PLUSBilling",
"returnUrl": "https://google.com/",
"status": "PENDING",
"test": true,
"trialDays": 0
},
{
"createdAt": "2025-02-26T03:29:40Z",
"currentPeriodEnd": "2025-03-28T03:30:53Z",
"id": "gid://shopify/AppSubscription/34265366817",
"name": "PLUSBilling",
"returnUrl": "https://google.com/",
"status": "ACTIVE",
"test": true,
"trialDays": 0
},
{
"createdAt": "2025-02-26T03:29:55Z",
"currentPeriodEnd": null,
"id": "gid://shopify/AppSubscription/34265399585",
"name": "PLUSBilling",
"returnUrl": "https://google.com/",
"status": "PENDING",
"test": true,
"trialDays": 0
},
{
"createdAt": "2025-02-26T03:30:04Z",
"currentPeriodEnd": "2025-03-28T03:30:25Z",
"id": "gid://shopify/AppSubscription/34265432353",
"name": "PLUSBilling",
"returnUrl": "https://google.com/",
"status": "ACTIVE",
"test": true,
"trialDays": 0
}
]