DEV Community

Cover image for Node-Locked vs. Floating Licenses: Which One Do You Need?
PermitCore
PermitCore

Posted on Originally published at permitcore.dev

Node-Locked vs. Floating Licenses: Which One Do You Need?

Originally published on the PermitCore blog.

Both options sit right next to each other on a typical Create License form, and it's not always obvious which one fits your product. The short version: node-locked ties a key to specific machines; floating ties a key to a pool of concurrent seats that any machine can borrow from. Here's when each one actually makes sense.

Node-Locked: One Key, Specific Machines

A node-locked license binds to a device's hardware fingerprint the first time it's activated, and stays bound until it's explicitly deactivated. MaxActivations is a hard ceiling on how many distinct devices can ever hold that key at once.

This is the right default for most desktop software: a customer buys one seat, installs it on their one work laptop, and that's that. It's simple to reason about, simple to support, and matches how most customers already think about "a license."

Floating: A Shared Pool of Seats

A floating license doesn't permanently tie itself to any machine. Instead, your app checks out a seat when it starts, and checks in (releases it) when it closes, or after a heartbeat timeout if it crashes without checking in cleanly. MaxActivations here means "how many machines can be actively using the software right now," not "how many machines have ever run it."

Floating license configuration showing seat pool and heartbeat settings

A 10-seat floating license lets any number of employees install the software, but only 10 can have it open at the same time.

This is the right fit for office software used by a team that's never all logged in simultaneously: CAD tools, analytics dashboards, anything where you'd rather sell "10 concurrent users" than "10 named installs."

// On app start
var session = await client.CheckoutFloatingSeatAsync(key);
if (!session.IsValid)
{
    // result.ErrorCode == "SeatsExhausted" means every seat is in use right now
    ShowNoSeatsAvailable();
    return;
}

// Periodically, while the app is running
await client.HeartbeatAsync(session.SessionId);

// On clean app shutdown
await client.CheckinFloatingSeatAsync(session.SessionId);
Enter fullscreen mode Exit fullscreen mode

Side by Side

Node-Locked Floating
Ties to a specific device a seat pool, any device
"Seats" means total installs ever concurrent active users
Needs activate/deactivate checkout/heartbeat/checkin
Best for 1 user, 1 machine shared office tools

What Happens If a Floating Session Never Checks In?

If a customer's machine crashes, loses power, or their app process is killed rather than closed cleanly, the seat isn't lost forever: a missed heartbeat past the configured timeout automatically frees the seat back into the pool for the next machine that needs it.

What's Next

Both models assume you're selling directly through your own app. The other distribution path is a built-in license store, for teams who want a real checkout page and automatic key delivery without building any of that themselves: Setting Up a License Store.

Which model do you use for your own desktop app, and did you ever have to switch? 🙂

Top comments (0)