Skip to content

Licensing & the license.key File

OperationsLicensingDeployment
Stable On by default · production-ready

A license is a single signed token in a file — license.key — that gates a deployment along five axes:

  • Size — maximum total database bytes.
  • Time — an expiry, followed by a grace window.
  • Upgrade window — the newest build the license permits.
  • Features — which capabilities the deployment has. HTAP, cluster mode and multi-tenancy exist only if the license grants them; see Feature entitlements.
  • Machine — optionally, the one host the key may run on; see Machine binding.

The token is Ed25519-signed. Only the vendor’s private signing key can mint one, and any edit to the size or date fields breaks the signature and is rejected immediately. Because the token is signed rather than secret, it needs no protected storage: it sits in plain text at /etc/aetherius/license.key, world-readable, and can be copied between machines that the license covers.

Signing makes a license unforgeable and tamper-evident. It does not make it tamper-proof — software checking a local file on hardware the customer controls is inherently bypassable by a patched binary, and no licensing scheme changes that. What the signature guarantees is that a valid token came from the vendor and says exactly what the vendor signed.

The single most important property: a license problem never stops the database from starting. A missing, expired, forged, or unreadable license degrades the daemon to read-only — reads keep working, writes are refused — and it boots normally either way. Your data is never stranded behind a licensing failure, and you always have a running server to read from and diagnose with.

That means “the daemon started” tells you nothing about license state. The boot banner does, and it is the one place license posture is reported.

The daemon resolves the license path in this order:

  1. --license-file <path> on the command line
  2. the AETHERIUS_LICENSE_FILE environment variable
  3. /etc/aetherius/license.key — used only if the file exists

There is no search relative to the daemon binary. Placing license.key next to /usr/local/bin/aetheriusd has no effect; the file must be at the configured path.

The installer places it for you: aether-install copies the key from the release tarball to <config_dir>/license.key and verifies its signature during installation, aborting the install if the key is present but invalid.

Terminal window
sudo install -d -m 0755 /etc/aetherius
sudo install -m 0644 ./license.key /etc/aetherius/license.key
# Verify BEFORE restarting — see the next section.
sudo aetheriusd verify-license --file /etc/aetherius/license.key
sudo systemctl restart aetheriusd # Linux
# sudo launchctl kickstart -k system/dev.aetherius.aetheriusd # macOS

The file is read-only to the daemon and read once at boot, so a replacement key takes effect on the next restart. 0644 is correct — the daemon reads it and never writes it, and the token carries no secrets.

aetheriusd is its own license verifier. Nothing else — no shell script, no installer — re-implements the check:

Terminal window
aetheriusd verify-license --file /etc/aetherius/license.key

On success it prints the decoded payload and exits 0:

license OK (valid): tier=1 size_cap=500 GiB expires_at_ns=1798761600000000000 upgrade_until_ns=1798761600000000000 id=42 format=2
feature htap=on (with license)
feature cluster=on (until 1783000000000000000)
feature multi_tenancy=off (license-only, not granted)
binding: 3f9a…c2e1 (MATCHES this machine)

A v1 key prints features: none granted and binding: none. Because the three license-only features are off unless granted, a v1 key means a daemon without HTAP, cluster mode or multi-tenancy; reissue the key with the grants you need before upgrading a deployment that uses them.

Exit codes are scriptable:

CodeMeaning
0Signature verified. The line also reports valid or EXPIRED.
1Invalid — bad magic, bad length, malformed encoding, or a signature that does not verify.
2The file could not be read (missing, or permissions).

Note the distinction in the success line: exit 0 means the signature is genuine. A genuine but expired token still exits 0 and prints EXPIRED. Check both.

Verification is against the public key embedded in that specific binary. A key minted for a different keypair fails on this binary even though it is perfectly valid elsewhere — which is the usual cause of an unexpected license INVALID: license: signature verification failed.

Some capabilities exist only when the key grants them. They cannot be enabled from the command line, the environment or RuntimeConfig on a licensed daemon.

Premium featureGrant nameWhere it is documented
HTAP — mutable Delta tier, snapshot isolation, write-conflict detectionhtapTransaction Isolation, Group Tables
Clustering — orchestrator, workers, distributed execution, cluster transactionsclusterCluster Execution Engine, Worker Node
Multi-tenancy — tenants beyond the system tenant, quotas, isolationmulti_tenancyMulti-Tenancy
High availability — standby VMs and the Shadow HA streamreplicationShadow HA Streamer

To license any of these, contact the AetheriusDB team at aetheriusdb.com or aetheriuslabs.com. Have the output of aetheriusd fingerprint ready if you want the key bound to one machine.

HTAP, clustering and multi-tenancy are enforced by the daemon today. The replication grant is carried in the key and printed by verify-license; the standby topology gates on it in an upcoming release.

A v2 token carries a list of feature grants: feature=on or feature=off, each with an optional expiry of its own. The daemon resolves every feature flag against that list at boot:

The license saysResult
feature=onThe feature is on, whatever the command line or environment says.
feature=offThe feature is off, whatever the command line or environment says.
nothing, and the feature is license-onlyOff. --enable-htap, AETHERIUS_ENABLE_HTAP, AETHERIUS_CLUSTER_MODE, AETHERIUS_WORKER_MODE and AETHERIUS_ENABLE_MULTI_TENANCY have no effect.
nothing, any other featureThe operator’s flag decides, as documented on the flags page.

The license-only features are htap, cluster and multi_tenancy. On a daemon that has evaluated a license (every shipped aetheriusd does, even when the key is missing) they come from the key alone. A worker started with AETHERIUS_WORKER_MODE and no cluster grant exits instead of serving.

Grantable feature names: htap, cluster, multi_tenancy, flight, external_cells, streaming_sources, replication, gpu, ai, autonomous_ops, branching, telemetry. Today the daemon enforces htap, cluster, multi_tenancy, flight, external_cells and autonomous_ops; the rest are carried and reported but do not yet have an enforcement point.

A grant with its own expiry (a trial) reads as absent once it passes, so a license-only feature switches off at the next boot after the trial ends. Change an HTAP entitlement only across a graceful restart: the shutdown reconcile flushes the Delta tier to sealed slabs, so the next boot without HTAP serves every row. A crash followed by a boot without the grant is the one sequence not yet proven safe.

The boot banner prints the resolved state on its own line:

license features: htap=on cluster=on | license-only: htap=on cluster=on multi_tenancy=off | binding: this machine

If --enable-htap appears to do nothing, this line is the reason.

A key may be bound to one machine. Binding works on a fingerprint:

Terminal window
aetheriusd fingerprint
# 3f9a…c2e1 (64 hex characters)

The fingerprint is a one-way BLAKE3 hash of the host’s stable machine identifier (/etc/machine-id on Linux, the platform UUID on macOS). Send it to the vendor; the key they issue carries the hash. At boot the daemon recomputes the local fingerprint and compares:

SituationResult
Key is unboundRuns anywhere.
Key is bound and matches this hostNormal operation.
Key is bound to another hostSignature verifies, but the daemon runs read-only with license bound to a different machine (read-only) in the banner.
Host has no machine identifierA bound key never matches; runs read-only.

The token reveals nothing about the host it is bound to, and the daemon never sends the fingerprint anywhere. There is deliberately no override variable for the machine id; one would make the binding a formality. In containers, bind-mount the host’s /etc/machine-id or use an unbound key. Reinstalling the operating system regenerates the machine id, so a bound key needs reissuing after an OS reinstall (not after a daemon upgrade).

verify-license reports the binding and whether it matches the host it is run on, so the check can be made before a restart.

Checking what the running database is actually enforcing

Section titled “Checking what the running database is actually enforcing”

Every boot prints one license line:

Terminal window
sudo journalctl -u aetheriusd -n 50 --no-pager | grep -i license
license: license active | size cap: 500.0 GiB | in use: 12.44 GiB (2.5%)

The reason field is the authoritative statement of posture. The full set:

Banner reasonModeWrites
license activeActiveallowed
license expired — grace period (writes warn)Graceallowed
license expired past grace (read-only)ReadOnlyrefused
no license file present (read-only)ReadOnlyrefused
license invalid or forged (read-only)ReadOnlyrefused
license bound to a different machine (read-only)ReadOnlyrefused
clock rollback detected (read-only)ReadOnlyrefused
build newer than licensed upgrade window (read-only)ReadOnlyrefused

Usage is printed alongside the cap deliberately: a cap-only line cannot distinguish a genuinely full database from a mis-accounted counter.

There is no SQL surface for license state — no system view, no SHOW command. The boot banner and verify-license are the only two ways to inspect it, which is why the banner line is worth capturing in whatever collects your daemon logs.

Reads are never gated — SELECT works in every mode. Mutations hit one of two errors.

Past grace, or with no valid license at all:

license read-only: writes are disabled (license expired past its grace window,
clock rollback, or no valid license). Reads remain available — install a valid
license to resume writes.

At the size cap (SQLSTATE 53100):

database size limit reached: 536870912000 of 536870912000 licensed bytes in use.
Delete rows to free space, or install a license with a larger size allowance.

The size cap gates INSERT only. UPDATE and DELETE stay available in every mode where writes are allowed at all, so you can always delete your way back under the cap — a size limit must never be able to lock you out of the operation that resolves it.

Expiry is not a cliff. Past expires_at_ns the daemon enters a grace window carried in the token: writes continue and are warned about. Only after grace elapses do writes stop.

The daemon re-evaluates on a timer, once every 24 hours by default, so a long-running server transitions Active → Grace → ReadOnly on its own without a restart. Installing a renewed key still requires a restart to be picked up.

Clock rollback is defended. The daemon persists a monotonic high-water-mark of observed time. If the wall clock jumps backwards beyond a five-minute skew tolerance, the deployment drops to read-only — moving the system clock back is not a way to extend an expired license. Legitimate NTP corrections fall well inside the tolerance; a VM restored from an old snapshot may not, so check the banner after any clock-affecting operation.

The upgrade window applies at boot. Each binary carries its build timestamp. If that timestamp is newer than the token’s upgrade_until_ns, the daemon runs read-only. This is the one failure mode that appears because you upgraded: the new binary starts fine, reads fine, and refuses writes. If writes stop immediately after an upgrade, check the banner before suspecting the data.

SymptomCauseFix
Banner says no license file presentFile is not at the resolved path — commonly placed next to the binaryPut it at /etc/aetherius/license.key, or set --license-file / AETHERIUS_LICENSE_FILE
verify-license exits 2Unreadable — missing file, or the daemon’s service user cannot read itCheck the path and 0644 permissions
verify-license exits 1Signature does not verify against this binary’s embedded key — on pre-release builds, most often a dev-vs-production keypair mismatch rather than a bad tokenConfirm which keypair the build was cut against; re-request the key if it genuinely does not match
Writes stopped right after an upgradeBuild is newer than the token’s upgrade windowDowngrade, or obtain a license covering the new build
Banner says bound to a different machineThe key was issued for another host’s fingerprint, or the OS was reinstalledRun aetheriusd fingerprint on this host and request a key bound to it, or an unbound key
--enable-htap / AETHERIUS_CLUSTER_MODE / multi-tenancy do nothingLicense-only feature with no grant in the keyCheck the license features: banner line; obtain a key granting htap / cluster / multi_tenancy
Writes stopped after a host clock change or snapshot restoreRollback defence trippedCorrect the system clock; the high-water-mark lives in the data dir
INSERT fails but SELECT/DELETE workSize cap reachedDelete rows, or install a larger-cap license

For any of these, the boot banner names the exact reason — start there rather than inferring posture from client errors.