What Happens After a Refund in Licensed Software
Issuing a license when someone pays is the easy, satisfying half of licensing. The other half — taking the license back when the money goes back — is where most home-grown systems quietly fall apart. This post walks through what should happen after a refund, and why.
The gap nobody plans for
Picture the normal happy path. A customer pays, your system mints a license key, the app unlocks. Everyone is happy.
Now the customer requests a refund. You click “refund” in Stripe. The money goes back. And… the license key still works. Nothing connected the refund to the license. The customer has their money and a working copy of your paid app.
This is not a rare edge case — it is the default outcome unless you specifically built against it. And it is not only refunds: chargebacks, failed subscription renewals, and expired trials all create the same gap. A license that can only ever be issued, never revoked, leaks revenue by design.
Revocation has to be automatic
The instinct is to handle it manually: when you process a refund, also go and revoke the key. That works at five refunds. It fails at fifty, because a manual step that depends on you remembering will, eventually, be forgotten — and a forgotten revocation is an invisible leak you never notice.
The reliable design makes revocation automatic, driven by the same events that move the money. Your payment processor already emits them. With Stripe:
charge.refunded— the customer was refunded.- A dispute event — a chargeback was filed.
customer.subscription.deleted— a subscription ended.
A licensing system listens for these and updates license state without anyone clicking anything. The refund and the revocation are the same action, so they cannot drift apart. This is part of what a native Stripe integration does — the webhook handling you would otherwise write and maintain yourself.
Chargebacks are not just slow refunds
It is worth treating chargebacks separately, because the timing differs.
A refund is something you grant — you decide, the money goes back, the license is revoked. A chargeback is something done to you: the customer disputes the charge with their bank, and the bank pulls the funds while it investigates.
Because the funds are already withheld and chargebacks frequently resolve against the merchant, the sensible policy is to revoke the license when the dispute is filed, not when it resolves. Waiting for resolution means weeks of a disputed customer using paid software you may never be paid for. Revoke on filing; if the dispute somehow resolves in your favour, you can reinstate.
How revocation reaches the app
Marking a license revoked on the server is only half of it. The app has to find out.
If your app uses offline license validation — and a desktop app should — it verifies the license locally on every launch and only re-checks with the server periodically. That means revocation is not instantaneous. A refunded customer who stays offline keeps a working app until the next online revalidation.
This sounds like a flaw; it is actually a deliberate, correct tradeoff. Instant revocation would require a server call on every single launch, which breaks the app for every honest customer who is ever offline. So the design accepts a delay: revocation lands on the next online re-check, typically within a few days. You lock out a refunded user slightly later in exchange for an app that always launches for the people who paid.
In the app, a revoked license simply resolves to an unlicensed state on the next revalidation:
await licensing.checkOnLaunch()
switch licensing.state {
case .licensed:
enablePaidFeatures()
case .expired, .invalid:
// A revoked license lands here after the next online revalidation
showRenewalPrompt()
case .trial(let daysLeft):
showTrialBanner(daysLeft: daysLeft)
}
The takeaway
A licensing system is not finished when it can issue keys. It is finished when a refund, a chargeback, and a lapsed subscription all flow automatically to a revoked license — with no manual step to forget. Build that path on day one, because every day without it is a day refunds quietly cost you twice.
If you handle refunds in a way worth a deeper write-up, send us your feedback.
Frequently asked
Does a license key stop working after a refund?+
It should. A well-designed licensing system listens for the refund event from the payment processor and marks the license revoked, so the app rejects it on the next online revalidation.
How fast does a refunded license stop working?+
With offline-first licensing, revocation lands on the app next online revalidation — typically within a few days — rather than instantly. That is the deliberate tradeoff for apps that must launch offline.
How are chargebacks handled differently from refunds?+
Chargebacks usually trigger revocation as soon as the dispute is filed, not after it resolves, because the outcome is frequently adverse to the merchant and the funds are already withheld.
Ready to ship?
Create your account and start licensing your apps in under a minute. Free forever tier included.
Start Free