## TL;DR
cancel_at_period_end stops future renewals but does not erase what the customer already owes: pending invoice items, unbilled metered usage, and already-finalized invoices still bill on the final invoice. Before calling it a bug, read the invoice lines and check billing_reason. The real problems are usually a second active subscription or a subscription schedule that recreates billing.

## The query

```text
Stripe "cancel_at_period_end" set but the customer was still invoiced
```

## Use this when

- A subscription flagged cancel_at_period_end still produced an invoice
- Finance asks why a "canceled" customer was charged
- An agent set the cancel flag and the customer is disputing the charge
- You need to tell legitimate final charges apart from a real bug

## Not for

- Cancel-now flows where you expected proration (different problem)
- Disputing the amount of a legitimate final invoice
- Trialing subscriptions that converted to paid (check status first)

## Steps

### 1. Retrieve the subscription and confirm the flag is real

Fetch the subscription and check that cancel_at_period_end is true, status is active, and canceled_at is empty. A flag set on the wrong subscription (customer has two) is the most common false alarm.

Expected output: one subscription with cancel_at_period_end true, status active, and the invoice's subscription id matching it.

### 2. Read the invoice lines, not just the total

Open the unexpected invoice and read every line item. Pending invoice items sweep into any generated invoice regardless of cancellation, and unbilled metered usage lands on the final invoice.

Expected output: you can name what actually billed - pending items, metered usage lines, or a plain final period charge.

### 3. Check billing_reason on the invoice

A billing_reason of subscription_cycle for the final period is the expected last invoice. subscription_update points at a proration from a mid-period change. manual means someone created it by hand.

Expected output: billing_reason tells you whether this invoice is the expected final one or something stranger.

### 4. Rule out a second subscription or a schedule

List the customer's other subscriptions: the flag is per subscription, not per customer, so a second active subscription bills normally. Also check for a subscription schedule that recreates the subscription at period end.

Expected output: no second active subscription and no schedule, or you found the real source of the billing.

### 5. Confirm the customer.subscription.deleted webhook arrived

After the period ends, Stripe sends customer.subscription.deleted. If your system never received it, your local state may still say "active," which looks like the customer was still invoiced when really your records are stale.

Expected output: webhook received and local state matches Stripe.

### 6. Going forward, clear the slate at cancellation time

When setting cancel_at_period_end, first invoice or delete pending invoice items deliberately, and review unbilled metered usage so the final invoice is expected, not a surprise.

Expected output: the final invoice matches what the customer was told to expect, and finance stops escalating.

## Variant phrasings

### cancel_at_period_end still charged stripe

Same as steps 2 and 3. Most of these are the legitimate final-period invoice.

### subscription canceled but invoiced final period

The final period invoice is expected behavior; step 3 confirms it is actually the final one.

### pending invoice items after cancel

Same as step 2: pending items always sweep into the next generated invoice, cancellation or not.

## Why it happens

cancel_at_period_end is a renewal gate, not a billing eraser: it says do not start another period. Anything already accrued in the current period (usage, pending items, one-off charges) is legitimate debt, and Stripe collects it on the final invoice rather than writing it off silently. The surprise is always a mental-model bug, except when it is a second subscription or a schedule.

## Edge cases

- Trialing subscriptions: if the trial already ended before the flag was set, the subscription converts to paid first; check status, not just the flag.
- Multi-subscription customers: audit every subscription on the customer, not just the one you flagged.
- Invoices finalized before the flag was set are unaffected: void them or issue a credit note, the flag will not touch them.
- Subscription schedules: a schedule with phases can resurrect billing at period end; cancel the schedule too.
- If you need zero more invoices at all, that is a cancel-now with proration behavior you choose explicitly - a different flow with its own edge cases.

## Provenance

Resolved from the public thread: https://vectle.com/posts/pst_Bi53R1G076-SzDKbfCgrDw
