Skip to main content

Idea

You can use floating licenses to limit how many copies of your application run in Docker or Kubernetes at the same time. In the setup below, each licensed application process uses one seat. It generates a random ID at startup, uses that ID as MachineCode to acquire a seat, and renews the seat while doing licensed work. A container image, hostname, or Pod identifier does not uniquely identify every application process. Containers can be copied, a Pod can contain multiple processes, and a process can restart within the same Pod. Do not use these shared or reusable values as the primary process identity.

Implementation

Generate the ID once per process startup, outside the heartbeat loop. Keep it in memory for that process’s lifetime; do not bake it into an image, persist it to a shared volume, or reuse it after a restart. Initialize an independent ID in each licensed worker, including workers created by forking.
Use the complete floating lifecycle:
  1. Acquire with Activate, using the process ID and a configured FloatingTimeInterval. Keep overdraft at 0 unless deliberately enabled.
  2. Validate the signature, expected product/license, features, blocking, applicable expiry, and the floating activation for this ID before enabling work.
  3. Renew with the same ID before the window expires. Use a consistent floating interval across processes and leave time for network delays and retries.
  4. Keep the last confirmed deadline unchanged after a failed renewal. Stop licensed work when it expires; a pending heartbeat cannot extend it.
  5. On shutdown, stop licensed work and stop scheduling renewals. Wait for any pending renewal to finish, then call Deactivate with Floating=true and the same ID.
GetKey and usage-counter updates are not heartbeats and do not renew seats. Usage counters measure consumption independently of concurrent-process capacity.

FAQ

Your application acquires a seat by calling Activate; Devolens does not count Kubernetes Pods automatically. An unrelated sidecar does not use a seat just because it shares the Pod. A worker or child process that independently performs licensed work needs its own ID and seat in this setup.
A restarted process gets a new ID even if it runs inside the same Pod. The old ID may still be using a seat until the floating window expires. If no seat is available, the new process must wait before starting licensed work.Scaling out increases the number of seats needed. Rolling updates can overlap old and new Pods, so allow capacity for that overlap or arrange for old processes to stop licensed work and release their seats before replacements begin licensed work. Keep processes that have not acquired a seat from accepting licensed jobs.Kubernetes can replace Pods, and a replacement has a different UID even if its name is reused. Containers can also restart within an existing Pod. This is why we generate a new ID when the application process starts. You can read more in the Kubernetes Pod lifecycle documentation.
Handle the process’s termination signal, normally SIGTERM, so it stops licensed work and stops scheduling renewals. Wait for any pending renewal to finish, then attempt floating deactivation. A Kubernetes preStop hook can help run these shutdown steps, but it cannot guarantee cleanup after a crash or node loss. The hook and process shutdown share the Pod’s termination grace period; allow enough time to stop work and send a deactivation request with a timeout. See container lifecycle hooks and Pod termination.If the process is killed, the node disappears, or the deactivation request is lost, its seat stays in use until the floating window expires. The new process may therefore have to wait even though the old one has stopped. An exit handler is not guaranteed to run, and the new process must not use the old process’s saved response to start licensed work.
For Docker or Kubernetes deployments with no direct Internet connection, consult the License Server guide and its offline floating setup for a licensing service reachable on the customer’s network.An ordinary cached signed license file can carry license information, but it cannot coordinate concurrent seats among Pods or processes. A longer offline cache age does not extend a floating process’s last confirmed validity window.