The Developer's Guide to License Key Rotation
It’s the email every indie developer dreads: "Hey, I found my license key for your app on a pirate forum. Can you help?"
Or perhaps it’s less dramatic: you have a customer who cancelled their subscription six months ago, but because you use a "buy once" model for your desktop app, they’re still receiving every single update you ship.
In the world of licensing, immortality is a bug.
License key rotation is the process of periodically (or reactively) replacing old keys with new ones. Most people think of it as a security chore, but for a small team, it’s actually a vital tool for revenue protection and customer hygiene.
Why You Actually Need to Rotate Keys
1. The "Stale Activation" Problem
Users lose laptops. They upgrade their MacBooks. They sell their old PCs without deactivating their software. Over time, your "3 device limit" becomes meaningless because 2 of those devices don't exist anymore, but the activations are still "active" on your server. Rotating keys (or forcing a re-activation) clears the slate.
2. The Leaked Key Cleanup
When a key gets leaked, you have two choices: ignore it (and lose money) or kill it (and annoy the legitimate buyer). Rotation allows you to issue a new key to the buyer while blacklisting the old one.
3. Price and Tier Shifts
Maybe you’re moving from a "Lifetime" model to a "Pro" model. Rotating keys allows you to "grandfather in" old users while ensuring that new features are only accessible to the new key tiers.
The "Golden Rule" of Rotation: The Grace Period
The biggest mistake developers make is instant revocation.
If you kill a license key at 2:00 PM on a Tuesday, and your user is in the middle of a client presentation, they will never forgive you. It doesn't matter if you sent them an email about it last week.
The Pro Move: Always implement a Grace Period. When you rotate a key, the old key should stay valid for 7 to 14 days. During that time, your app should show a non-intrusive notice: "Your license key has been updated for security. Please click here to refresh." This gives them time to react without breaking their workflow.
Manual vs. Automated Rotation
The Manual Way (The "Emergency" Route)
You do this in response to a specific event (like a refund or a leak). You go into your Keymint dashboard, revoke the old key, and generate a new one. This is fine for one-offs, but it's slow.
The Automated Way (The "Hygiene" Route)
You can set your licensing system to rotate keys automatically after a certain period—for example, every 12 months.
- How it works: Your backend checks the key's expiry via the
GET /keyendpoint using aread-onlyoradminAPI key. If rotation is needed (e.g., the key is approaching its rotation schedule), you block the old key and issue a new one, then deliver it to the user. The old key remains valid during a grace period so the user isn't interrupted.
A Sample Rotation Workflow
If you're using a licensing API like Keymint, the logic is straightforward. Here's how you would handle an automated rotation check:
// Run this server-side with a read-only or admin API key.
// Client-scope keys should use activate/checkout flows instead.
const checkRotation = async (currentKey, productId) => {
const url = `https://api.keymint.dev/key?productId=${productId}&licenseKey=${currentKey}`;
const response = await fetch(url, {
headers: { 'Authorization': `Bearer ${token}` }
});
const { data } = await response.json();
const key = data?.license;
// If the key is nearing its rotation date, notify the user
if (key && key.expirationDate) {
const daysUntilExpiry = (new Date(key.expirationDate) - new Date()) / 86400000;
if (daysUntilExpiry < 30) {
// 1. Alert the user: "Your license key will expire soon."
// 2. Issue a new key via the dashboard or createKey API using an admin key
// 3. Ask the user to enter the new key (or auto-replace with a grace period)
}
}
}If you need to revoke a compromised key, block it and issue a replacement (see our revocation guide for the full flow):
These operations require an admin API key.
# Block the old key
curl -X POST "https://api.keymint.dev/key/block" \
-H "Authorization: Bearer YOUR_ADMIN_API_KEY" \
-d '{
"productId": "prod_100",
"licenseKey": "OLD-COMPROMISED-KEY"
}'
# Create a replacement key
curl -X POST "https://api.keymint.dev/key" \
-H "Authorization: Bearer YOUR_ADMIN_API_KEY" \
-d '{
"productId": "prod_100",
"maxActivations": "5"
}'Don't Let Your Licenses Stagnate
A healthy licensing system is a dynamic one. By building rotation into your app early, you protect yourself from piracy and make your business more resilient to the inevitable "price shifts" and "tier changes" that come with growth.