FAILED PAYMENTSLEMON SQUEEZY

How Lemon Squeezy handles failed subscription payments

What happens on Lemon Squeezy when a renewal fails: past_due and unpaid statuses, the four retries, dunning emails, webhooks, and what you can add on top.

Published 6 min read

When a subscription renewal fails on Lemon Squeezy, a lot happens without you doing anything: the charge is retried, the customer gets emails, and the subscription moves through a few statuses before it ends. Knowing exactly what Lemon Squeezy does, and what it leaves to you, is the difference between a customer who quietly drops off and one who updates their card.

This guide walks through that lifecycle step by step, then gives practical advice you can apply in your own app. It sticks to Lemon Squeezy’s own documentation: the Recovery and Dunning help page, the Subscription object reference, the webhook event types and the Subscriptions help page (all accessed November 2026). Where the docs do not say something, we say so.

The failed payment lifecycle on Lemon Squeezy

Lemon Squeezy is a merchant of record: it charges the customer, runs the retries and sends the billing emails. Your job is mostly to react to status changes in your app.

Step 1: the renewal fails and the subscription goes past_due

According to the Subscription object reference, when a renewal payment fails the subscription status becomes past_due. The subscription then goes through 4 payment retries over the course of 2 weeks. If one of those retries succeeds, the status goes back to active.

The Recovery and Dunning page adds two details:

  • During the retries, the subscription still counts as active from an access point of view: the customer keeps using your product.
  • Each failed attempt triggers an email asking the customer to update their billing details.

Step 2: retries run out and the subscription becomes unpaid

If all retries fail, the status moves to unpaid. This is where Lemon Squeezy’s dunning starts. Per the Recovery and Dunning page, dunning emails are sent over a set period, and each one links to a page where the customer can update their payment details and reactivate.

Step 3: dunning ends, or the subscription stays unpaid

What happens after that depends on your Recovery settings:

  • You can set a delay after which the subscription is automatically cancelled. Once that happens, the customer can no longer reactivate it.
  • You can leave the subscription unpaid, which lets the customer reactivate it at any time.
  • If you turn dunning off, the status simply stays unpaid, and it is up to you to decide what that means for access.

When dunning completes, Lemon Squeezy sends subscription_expired, which its event types page describes as firing “once dunning has been completed for past_due subscriptions”.

PayPal is different

The Recovery page notes that PayPal subscriptions follow a different retry cadence, with attempts every 5 days. If a meaningful share of your customers pay with PayPal, do not assume the card timeline applies to them.

Statuses at a glance

Status What it means Should the customer have access?
active Paid and in good standing Yes
past_due Renewal failed, retries in progress (4 over about 2 weeks) Yes, per Lemon Squeezy
unpaid Retries exhausted, dunning running or dunning off Your call; Lemon Squeezy’s lifecycle docs say access should end only at expired
cancelled Cancelled, in its grace period until ends_at Yes, until ends_at
expired Ended No

The Subscriptions help page says customers should keep access in every status except expired. Some teams prefer to restrict features while unpaid; if you do, say so clearly in your app so the customer knows why.

The webhooks you need

The event types page lists the subscription events. For failed payments, these four matter:

Event When it fires Payload
subscription_payment_failed A renewal payment fails (not the first payment) Subscription invoice object
subscription_payment_recovered A payment succeeds after a failure Subscription invoice object
subscription_payment_success Any successful payment; always sent alongside subscription_payment_recovered Subscription invoice object
subscription_updated Any change to the subscription, including status changes Subscription object
subscription_expired After a cancelled subscription ends, or once dunning completes Subscription object

Two things to note. First, subscription_payment_failed carries a subscription invoice object, not the subscription itself, so you will usually fetch the subscription to read its status. Second, Lemon Squeezy says subscription_updated fires on every change after the initial payment, so for many apps it is enough to listen to it and read status.

The docs we used do not describe a decline reason field comparable to card network decline codes on these events, so do not build logic that depends on one without checking your own payloads.

Every subscription object has a urls attribute with an update_payment_method link: a pre-signed URL where the customer can change their card. The Subscription object reference says these signed URLs are valid for 24 hours, and the managing subscriptions guide makes the same point for recovery links: fetch the subscription again to get a fresh one rather than storing it.

That has a practical consequence. If you send your own emails, do not paste a stored link into an email that might be opened three days later. Link to a page in your app that fetches a fresh URL and redirects.

Configuring Recovery settings

Lemon Squeezy’s dunning emails are configured on the Recovery settings page of your store. The Recovery and Dunning page says you can enable or disable dunning and edit the emails, subject lines, content and delivery schedule, with defaults provided.

A sensible setup:

  1. Keep dunning on. It costs nothing and it reaches customers who never open your app.
  2. Rewrite the default copy in your voice. Say what the product is, what happens if the card is not updated, and keep one clear button.
  3. Decide on automatic cancellation deliberately. Leaving subscriptions unpaid keeps the door open for reactivation. Auto-cancelling gives you a clean end date. Pick one and make your app’s access rules match it.
  4. Test it. Lemon Squeezy’s test mode lets you simulate webhook events, so you can check your app’s reaction to past_due, unpaid and expired before a real customer hits them.

Practical advice you can apply today

Lemon Squeezy’s built-in behavior is a solid baseline. The gaps are mostly on your side of the integration.

1. Show the problem inside your app

Billing emails get filtered. When a subscription is past_due or unpaid, show a banner in your app with a button to your “update card” route. This is often the moment the customer is most likely to act, because they are already using the product.

2. Handle statuses explicitly

Map every status to an access rule in one place in your code. A common bug is treating anything other than active as “no access”, which locks out past_due and cancelled customers who have paid for their current period.

3. Verify and deduplicate webhooks

Lemon Squeezy signs each request with an HMAC in the X-Signature header (signing requests) and retries non-200 responses up to three more times with exponential backoff (webhook requests). Verify the signature against the raw body and make your handler safe to run twice.

4. Send one human message

The automatic emails cover the mechanics. A short, plain message from a real person (“Your card didn’t go through, here’s the link, reply if anything’s wrong”) often lands differently. Send it once, around the time the subscription becomes unpaid, not on every failed attempt.

5. Track recovery

Count subscription_payment_failed events and subscription_payment_recovered events per month. The ratio is your own recovery rate, measured on your data. If it moves after a copy change, you know the change mattered.

Doing this with NoChurn

Lemon Squeezy keeps running the payment, the retries and its own dunning emails; NoChurn does not replace that. NoChurn reads your Lemon Squeezy webhooks, puts every failed payment in one timeline, and can add AI-written recovery emails that you review before they are sent. It also gives each customer a churn score from 0 to 100, and disputes, which Lemon Squeezy handles as the merchant of record, appear read only. NoChurn is free under $300 MRR with all features on every plan. See NoChurn + Lemon Squeezy.

PROMPT

Read https://www.nochurn.sh/llms.txt,
then follow https://www.nochurn.sh/docs/quickstart/
to add NoChurn to this app. Use a test key
(nc_test_…) until I say we go live.

Stop leaking revenue.

  • Free until $300 MRR
  • No card needed
  • Live in 10 minutes
  • Never a cut of what we recover