Price increase notification before new-rate renewal
Why it matters
Charging a consumer at a higher price than they originally authorized — with no advance notice — violates the FTC Negative Option Rule (2025) requirement that material changes to subscription terms be communicated before they take effect. California ARL and EU Consumer Rights Directive 2011/83/EU both require that price increases be disclosed with sufficient advance notice for the consumer to cancel before the new rate applies. Silent price increases processed through Stripe Subscription Schedules without customer notification are the most common way well-intentioned teams inadvertently create regulatory exposure during pricing strategy updates.
Severity rationale
Info because the violation requires a price change event to occur — no prior price change means no current violation — but the absence of a notification mechanism means any future price change immediately creates regulatory liability.
Remediation
Handle customer.subscription.updated to detect price changes and trigger a 30-day-advance notification email. In app/api/webhooks/stripe/route.ts:
const priceChanged = prevSub?.items &&
newSub.items.data[0]?.price.id !== prevSub.items.data?.[0]?.price?.id
if (priceChanged && email) {
await sendEmail({
to: email,
subject: 'Important: Your subscription price is changing',
template: 'price-change-notification',
data: {
oldPrice: (prevSub.items.data?.[0]?.price?.unit_amount ?? 0) / 100,
newPrice: (newSub.items.data[0]?.price.unit_amount ?? 0) / 100,
effectiveDate: formatDate(newSub.current_period_end),
cancelUrl: `${process.env.NEXT_PUBLIC_APP_URL}/settings/billing`,
},
})
}
For planned increases, use Stripe Subscription Schedules with a future-dated phase so the notification goes out before the phase activates — not simultaneously with the price change.
Detection
-
ID:
price-change-notification -
Severity:
info -
What to look for: Check the application's handling of Stripe price changes. Look for webhook handlers for
customer.subscription.updatedthat check whetheritems.data[0].pricechanged, and whether a price-change notification email is triggered. Also check Stripe's built-in price change notification: when you update a price in Stripe, you can optionally notify affected customers — verify whether this is configured. Look for any price migration logic in the codebase: if the application has ever changed prices, how was the customer communication handled? Check forphaseobjects instripe.subscriptions.list— subscription schedules with multiple phases indicate a planned price change. If phases are set up, verify that affected customers receive advance notice. Count all instances found and enumerate each. -
Pass criteria: When a subscription price increases, affected customers are notified before the new rate takes effect. Notification includes the old price, the new price, the effective date, and the option to cancel before the new rate applies. At least 1 implementation must be confirmed.
-
Fail criteria: No mechanism exists to notify customers of price changes before they are charged at the new rate. Price changes are applied silently on the next billing cycle.
-
Skip (N/A) when: The application has no paid subscription features whatsoever (entirely free or one-time purchase only). Do NOT skip simply because no price change has occurred yet or there is no Stripe Subscription Schedule configured — any paid subscription product that lacks a price-change notification mechanism should fail this check, not skip it. Absence of prior price increases is not grounds to skip; the question is whether a mechanism exists for when prices do change.
-
Detail on fail: Example:
"No customer.subscription.updated handler for price changes. Stripe subscription schedules are in use for a planned price increase but no customer notification email is configured."or"Price change notification is not implemented. Stripe's built-in price change email is not enabled in Dashboard settings.". -
Remediation: Notify customers of price changes at least 30 days in advance:
// app/api/webhooks/stripe/route.ts if (event.type === 'customer.subscription.updated') { const newSub = event.data.object const prevSub = event.data.previous_attributes // Check if the price changed const priceChanged = prevSub?.items && newSub.items.data[0]?.price.id !== prevSub.items.data?.[0]?.price?.id if (priceChanged) { const customer = await stripe.customers.retrieve(newSub.customer as string) const email = 'email' in customer ? customer.email : null if (email) { await sendEmail({ to: email, subject: 'Important: Your subscription price is changing', template: 'price-change-notification', data: { oldPrice: (prevSub.items.data?.[0]?.price?.unit_amount ?? 0) / 100, newPrice: (newSub.items.data[0]?.price.unit_amount ?? 0) / 100, effectiveDate: formatDate(newSub.current_period_end), cancelUrl: `${process.env.NEXT_PUBLIC_APP_URL}/settings/billing`, }, }) } } }For planned price increases, send the notification well in advance (30+ days) using Stripe Subscription Schedules rather than immediate price updates.
External references
- external · ftc-negative-option-rule-2025 — FTC Negative Option Marketing Rule (2025) — material change notification and consent
- external · california-arl — California Automatic Renewal Law (Bus. & Prof. Code §17602(d)) — price change notification before renewal
- external · eu-consumer-rights-directive-2011-83-eu — EU Consumer Rights Directive 2011/83/EU Art. 11 — durable medium notice of material contract changes
Taxons
History
- 2026-04-18·v1.0.0·Initial import from subscription-compliance·automated