---
title: "Comment by Paul Hartness on \"Stripe webhooks in the Next.js App Router: signature checks, idempotency and the bugs AI assistants leave\" | Hashnode"
description: "The \"gate access on your database, not the redirect\" point is the one that bites later. Worth deciding up front what access looks like while a subscription is p"
url: "https://hashnode.com/posts/stripe-webhooks-in-the-next-js-app-router-signature-checks-idempotency-and-the-bugs-ai-assistants-leave/6ae4a4e30d7ed2e767de6cb3/comment/6ae859b5807a1760b478c28b"
---

[Discussion](https://hashnode.com/posts/stripe-webhooks-in-the-next-js-app-router-signature-checks-idempotency-and-the-bugs-ai-assistants-leave/6ae4a4e30d7ed2e767de6cb3)

Comment [Stripe webhooks in the Next.js App Router: signature checks, idempotency and the bugs AI assistants leave](https://hashnode.com/posts/stripe-webhooks-in-the-next-js-app-router-signature-checks-idempotency-and-the-bugs-ai-assistants-leave/6ae4a4e30d7ed2e767de6cb3)

[Paul Hartness](https://hashnode.com/@retryfix)

[Nov 2](https://hashnode.com/posts/stripe-webhooks-in-the-next-js-app-router-signature-checks-idempotency-and-the-bugs-ai-assistants-leave/6ae4a4e30d7ed2e767de6cb3/comment/6ae859b5807a1760b478c28b)

The "gate access on your database, not the redirect" point is the one that bites later. Worth deciding up front what access looks like while a subscription is past\_due: Stripe keeps retrying for a while, and cutting access on the first invoice.payment\_failed locks out people whose card would have cleared on the next attempt. Keeping access until the status actually moves to canceled or unpaid tends to be kinder and simpler.

[ArkNet Digital](https://hashnode.com/@arknetdigital)

[2d ago](https://hashnode.com/posts/stripe-webhooks-in-the-next-js-app-router-signature-checks-idempotency-and-the-bugs-ai-assistants-leave/6ae4a4e30d7ed2e767de6cb3/comment/6ae859b5807a1760b478c28b#reply-6af2202c67b90e779f8c3035)

Thanks, Paul — that's the failure mode we see most after the first launch week.

We treat `past_due` / `unpaid` as a soft gate: keep read access to the customer's own data, block new paid actions, and flip to hard revoke only after the last Stripe retry fails (or after an explicit `customer.subscription.deleted`). That way a card update during the retry window doesn't strand them behind a login wall that the webhook can't reach.

Worth deciding that matrix (active / past\_due / unpaid / canceled) in the same PR as the webhook handlers, not after the first dunning email lands.
