Home / Blog / License delivery
License delivery

Which parts of a perpetual license should keep working after the update window expires?

A perpetual license makes two promises with two different clocks: the right to run the software forever, and the right to receive new builds for a while. Here is how to separate them cleanly in your data model, your binary, and your support scripts.

A tidy home office desk at golden hour with two closed laptops of different ages stacked beside a ceramic coffee mug, warm lamp light, wooden surface, small potted plant, soft shadows

A perpetual license is two promises, not one

A perpetual license is really two promises stacked on top of each other, and most support arguments happen because only one of them ever got written down. The first promise is the right to run the software you sold, indefinitely, on the terms in effect at purchase. The second is the right to receive new builds for some period after that, commonly twelve months for small desktop products. Those two promises run on different clocks. When a team encodes a single expiry date and applies it to both, the customer who stopped paying for updates opens the app one morning and finds it refusing to launch, which is not what either side agreed to. Related: Why Digital Products Need Licensing

Write the distinction into the license record before you write it into code. A row that carries a purchase date, an update entitlement end date, and a separate status field for the run right lets you answer every awkward question later: can this person reinstall, can they open the build they already have, can they download the patch you shipped last week. If your schema only has one field called expiresAt, someone will eventually overload it to mean three things at once, and overloaded fields are where licensing bugs come from. Related: Generating License Keys That Work

Keep reading: Why Digital Products Need Licensing, Generating License Keys That Work, Validating Keys Without Frustrating Users. See how KeyDispense helps you digital product license key issuing and validation api.

Gate on build release date, not on version numbers or the clock

The rule that survives contact with reality is simple: a build is allowed if its release date falls on or before the entitlement date recorded in the license. Stamp every build with its own release date at compile time and compare that stamped value against the date in the license. Do not compare against the current system time, because the current time says nothing about what the customer bought. Do not compare version numbers alone either, because numbering schemes change, hotfix branches make ordering ambiguous, and a 4.2.1 patch built for an old line can easily be newer in calendar terms than a 5.0 release. Related: What is the best way to structure trial keys so they convert to paid?

Put the entitlement date inside a signed license payload rather than looking it up on every launch. The app verifies the signature with a public key embedded in the binary, reads the update entitlement field, and decides locally whether the build in front of it is covered. That keeps the check working offline, keeps your validation endpoint out of the startup path, and means a customer whose maintenance lapsed does not need your servers reachable to keep using what they own. Refresh the signed payload opportunistically whenever the app happens to be online, and let the previous one stay valid until it is replaced. Related: How do you activate a license when the customer's machine never touches the internet?

What keeps working forever, and what genuinely stops

Everything the customer already has should keep working, and that list is longer than most teams remember. The installed version keeps launching. Reinstalling on the same machine after a disk failure works. Activating on a replacement laptop works, because hardware dies long after maintenance windows close, and refusing that activation is the single fastest way to turn a quiet customer into a public complaint. Older installers stay downloadable from a page the customer can reach with their key. Saved projects, exports, and any file format your app created stay readable. None of that should require a live entitlement.

What actually stops is narrower: access to builds released after the entitlement date, and any hosted service you pay real money to operate, such as a sync backend or a cloud render queue. Security patches are the honest judgment call. Our position is that a critical fix for a version the customer is entitled to should reach them regardless of maintenance status, because the alternative is unpatched copies of your software running in the world with your name on them. Whichever way you land, publish the policy in writing so it is not relitigated in every ticket.

Interface and support work that prevents the arguments

The window closing should be a calm, expected event rather than a surprise. Show the entitlement date in an about panel or account screen from the first day, so it is never news. When a newer build exists but is not covered, say so before the download starts, alongside the renewal price and exactly what renewing includes. The worst version of this flow is an installer that runs happily, replaces a working application, and only then discovers the license does not cover it. Check entitlement before you overwrite anything, and keep the previous install recoverable.

Support staff need two things and rarely have either. First, a lookup that shows purchase date, entitlement end, activation history, and current status on one screen, so an agent is not stitching together a payment dashboard and a database. Second, a bounded override: the ability to extend an entitlement by a fixed number of days with a required note, without anyone touching production data by hand. Most tickets here are honest confusion, a renewal that was paid but never applied, or someone who upgraded by accident. Read the override notes monthly, because they tell you whether the policy or the interface is the thing that needs fixing.

Key takeaways
  • Model the right to run and the right to update as two separate fields with two separate dates.
  • Allow a build when its stamped release date falls on or before the license entitlement date, never by version number or system clock.
  • Reinstalls, replacement hardware activations, and access to older installers must keep working after maintenance lapses.
  • Decide and publish your security patch policy before the first lapsed customer asks about it.
Julien Jimenez
Written by

Julien Jimenez

Julien Jimenez is an independent software builder based in Paris. He designs, ships, and operates focused SaaS products for small businesses and independent professionals. Read the full author page.

Issue and validate license keys with one API

Digital product license key issuing and validation API. KeyDispense is built to help you put this into practice.

Get an API key

More from the KeyDispense blog

Get the KeyDispense playbook

Practical guides on license delivery, straight to your inbox as we publish them. No spam, unsubscribe any time.

By subscribing you agree to our privacy policy.