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
| Pattern | Typical API | Customer experience |
|---|---|---|
| Immediate | DELETE subscription | Access ends per your product rules when deleted fires |
| Classic period end | cancel_at_period_end=true | Paid period completes; deleted at period end |
| Scheduled timestamp | cancel_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
- Use test clocks for period-end cancels — test cancellation flow locally
- Assert both updated and deleted handlers for end-of-period flows
Wire cancel timing in your app
ChurnIntel completes voluntary cancels server-side after your flow — map timing to Stripe per reason.