Urgent.News

What's breaking now, across thousands of outlets.

Tech

Stripe said "Cancels". My dashboard said "Renews". The webhook returned 200 the whole time.

I run a small subscription SaaS on Next.js, Drizzle and Postgres, billed through Stripe. Before opening it up to real customers I did the most boring test there is: I became a customer in production. Real card, real trial, real Customer Portal. Then I canceled. Stripe's side looked perfect. The subscription showed a clear "Cancels" badge with the end date. My own dashboard, the page my customers…

A small subscription SaaS built with Next.js, Drizzle, and Postgres was integrated with Stripe Billing. To test the system before going live, the author used a real card, trial period, and Customer Portal. After canceling the test subscription, the expected "Cancels" badge appeared in Stripe's side, but the author's dashboard still showed "Renews" until they refreshed the page.

The webhook responses for the cancellation were successful (200), and the runtime logs showed no errors. However, the dashboard's displayed information was incorrect.

The author's handler for Stripe events fetched the subscription from Stripe for each event, ensuring that any older or out-of-order events wouldn't overwrite newer state. The function that displayed the dashboard information read the "cancel_at_period_end" boolean, which determined whether to display "Cancels" or "Renews". In this case, the boolean was set to false, so "Renews" should have been displayed.

The author first suspected a race condition due to multiple cancellation events. However, they quickly ruled this out because the handler already fetched the latest subscription state from Stripe for each event. They also had to confirm their suspicions by checking Stripe's event logs, as their local runtime logs had been deleted. The cancellation event's previous attributes confirmed that the "cancel_at_period_end" field was set to false, regardless of the "cancel_at_period_end" boolean in the subscription object.

The solution was to stop reading the "cancel_at_period_end" boolean and instead read the "cancel_at" timestamp, which was set during the cancellation event. The author realized that "cancel_at_period_end" was deprecated and no longer accurate for subscriptions on the flexible billing mode. The field's value became irrelevant once the billing mode changed to "flexible", as the absolute end date for the subscription was set using the "cancel_at" timestamp instead.

Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.

Read the original at dev.to →

More in Tech

More from Wednesday 23 September →