Documentation · SoftActivate Licensing

Floating licenses

A floating license permits N simultaneous seats among any number of devices. Ten developers can share five seats of a tool, as long as no more than five run it at once. The SDK needs no new calls: floating licenses use the same validate, renew, and deactivate calls as any other license.

How seats are held

Your app takes a seat when it activates and holds that seat only while its lease stays current. validate_license() (ValidateLicenseAsync in .NET) renews the lease automatically. Renewal happens well before the lease expires, so an application that validates regularly does not lose its seat by accident. If the app closes, the machine is wiped, or a VM is destroyed, the lease expires on its own and the seat frees itself with no explicit action required.

What your application should do

  1. Validate on a cadence, not only at startup. The seat is held by renewal, and renewal happens inside validation. Call it at least twice within each lease period while the app runs: a periodic timer, or a natural checkpoint such as "every job" for a build agent. Ask your vendor what the lease duration is and size your validation cadence to it.
  2. Deactivate on exit. Deactivating frees the seat immediately instead of waiting for the lease to expire, which keeps a shared pool responsive. Crashes are fine, because lease expiry is the backstop.
  3. Handle SEAT_LIMIT gracefully:

C++

#include "softactivate/sws_licensing.h"
#include <iostream>

auto client = sws::licensing::client::create(endpointUrl);
client->set_metadata("trusted_domain", trustedDomain);
client->set_vendor_id(vendorId);
client->set_license_key(customerLicenseKey);

auto params = client->create_license_validation_params();
auto result = client->validate_license(params);

if (!result->is_license_valid() &&
    result->get_status() == SWS_LICENSE_STATUS_SEAT_LIMIT)
{
    // every seat is held by a live lease; the message carries the soonest lease
    // expiry in seconds ("" if unknown) - the earliest a retry can succeed
    std::cerr << "All seats are in use; a seat frees in about "
              << result->get_status_message() << " seconds\n";
    // schedule a retry for then - never busy-poll faster than the hint
}

C#

using System;
using SWS.Licensing;

var client = new LicensingClient(endpointUrl)
{
    VendorId = vendorId,
    LicenseKey = customerLicenseKey,
    TrustedDomain = trustedDomain
};

LicenseValidationResult result = await client.ValidateLicenseAsync(null);

if (!result.IsValid && result.Status == LicenseStatus.SeatLimit)
{
    // every seat is held by a live lease; the message carries the soonest lease
    // expiry in seconds ("" if unknown) - the earliest a retry can succeed
    Console.Error.WriteLine(
        $"All seats are in use; a seat frees in about {result.StatusMessage} seconds");
    // schedule a retry for then - never busy-poll faster than the hint
}

VB.NET

Imports System
Imports SWS.Licensing

Dim client As New LicensingClient(endpointUrl) With {
    .VendorId = vendorId,
    .LicenseKey = customerLicenseKey,
    .TrustedDomain = trustedDomain
}

Dim result As LicenseValidationResult = Await client.ValidateLicenseAsync(Nothing)

If Not result.IsValid AndAlso result.Status = LicenseStatus.SeatLimit Then
    ' every seat is held by a live lease; the message carries the soonest lease
    ' expiry in seconds ("" if unknown) - the earliest a retry can succeed
    Console.Error.WriteLine(
        $"All seats are in use; a seat frees in about {result.StatusMessage} seconds")
    ' schedule a retry for then - never busy-poll faster than the hint
End If
  1. Expect to lose an abandoned seat. A machine that goes dark past its lease and later returns re-acquires a seat like any other device, and may receive SEAT_LIMIT if none are free.

Choosing a lease duration (for vendors)

Set the lease duration per template in the console. Three forces trade off against each other:

  • Short leases tighten security: a lost or reclaimed seat stops validating sooner, and a crashed machine's seat recovers faster.
  • Long leases tolerate being offline longer: a device can keep running without reaching the service for as long as its lease lasts. Borrowing a seat for a flight, for example, means choosing a longer lease.
  • Request volume matters at scale: every renewal is a round trip to the service, so very short leases across a large fleet add up.

Leases can be short: the console enforces a minimum, so you cannot set one that is impractically brief. Build-agent pools typically want lease durations measured in minutes to hours; desktop tools, hours to days. Seat occupancy and force-release are available on the license's page in the console (console guide).

One scoping note: floating licenses depend on a live connection. They cannot use the offline activation exchange.