Guide

Stripe Scheduled Cancellation: Immediate, Period End, and cancel_at

Customers expect different outcomes from “Cancel”: stop now, or finish the paid period then leave. Stripe represents those outcomes with DELETE, cancel_at_period_end, and cancel_at (timestamp or billing-mode helpers). Your UI copy, entitlements, and webhook handlers must match the fields you set — especially when the Customer Portal schedules a cancel on flexible billing mode.

This guide focuses on timing and subscription fields only. Webhook detail: Stripe cancellation webhooks. Full architecture: build a Stripe cancellation flow.

Last updated October 23, 2026

Three cancel patterns

PatternTypical APICustomer experience
ImmediateDELETE subscriptionAccess ends per your product rules when deleted fires
Classic period endcancel_at_period_end=truePaid period completes; deleted at period end
Scheduled timestampcancel_at set (incl. min_period_end / max_period_end)Cancel on a specific time; portal flexible paths

Billing mode changes the fields you read

On flexible billing mode, scheduled portal cancels may set cancel_at while cancel_at_period_end stays false. Handlers that only check cancel_at_period_end will mis-report access. Read billing mode comparison and the cancel subscriptions guide before coding guards.

Authoritative behavior tables: cancel subscriptions.

Access between schedule and deletion

  • Treat subscription.updated as the moment a future cancel becomes visible in Stripe
  • Keep access through paid period unless product policy says otherwise
  • Show in-app messaging when cancel_at or cancel_at_period_end is set
  • Do not revoke on updated alone if deleted has not fired yet

Proration caution on cancel_at

Setting cancel_at inside the current period can change proration behavior depending on billing_mode and update parameters. Do not copy one proration recipe from a blog post — confirm against your account API version and Stripe’s cancel documentation.

Test scheduled paths

Wire cancel timing in your app

ChurnIntel completes voluntary cancels server-side after your flow — map timing to Stripe per reason.