Licensing & the license.key File
What it is
Section titled “What it is”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.
Why it matters
Section titled “Why it matters”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.
Where the file lives
Section titled “Where the file lives”The daemon resolves the license path in this order:
--license-file <path>on the command line- the
AETHERIUS_LICENSE_FILEenvironment variable /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.
Installing or replacing a key
Section titled “Installing or replacing a key”sudo install -d -m 0755 /etc/aetheriussudo 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 # macOSThe 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.
Verifying a license
Section titled “Verifying a license”aetheriusd is its own license verifier. Nothing else — no shell script, no
installer — re-implements the check:
aetheriusd verify-license --file /etc/aetherius/license.keyOn 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=2feature 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:
| Code | Meaning |
|---|---|
0 | Signature verified. The line also reports valid or EXPIRED. |
1 | Invalid — bad magic, bad length, malformed encoding, or a signature that does not verify. |
2 | The 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.
Premium features
Section titled “Premium features”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 feature | Grant name | Where it is documented |
|---|---|---|
| HTAP — mutable Delta tier, snapshot isolation, write-conflict detection | htap | Transaction Isolation, Group Tables |
| Clustering — orchestrator, workers, distributed execution, cluster transactions | cluster | Cluster Execution Engine, Worker Node |
| Multi-tenancy — tenants beyond the system tenant, quotas, isolation | multi_tenancy | Multi-Tenancy |
| High availability — standby VMs and the Shadow HA stream | replication | Shadow 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.
Feature entitlements
Section titled “Feature entitlements”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 says | Result |
|---|---|
feature=on | The feature is on, whatever the command line or environment says. |
feature=off | The feature is off, whatever the command line or environment says. |
| nothing, and the feature is license-only | Off. --enable-htap, AETHERIUS_ENABLE_HTAP, AETHERIUS_CLUSTER_MODE, AETHERIUS_WORKER_MODE and AETHERIUS_ENABLE_MULTI_TENANCY have no effect. |
| nothing, any other feature | The 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 machineIf --enable-htap appears to do nothing, this line is the reason.
Machine binding
Section titled “Machine binding”A key may be bound to one machine. Binding works on a fingerprint:
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:
| Situation | Result |
|---|---|
| Key is unbound | Runs anywhere. |
| Key is bound and matches this host | Normal operation. |
| Key is bound to another host | Signature verifies, but the daemon runs read-only with license bound to a different machine (read-only) in the banner. |
| Host has no machine identifier | A 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:
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 reason | Mode | Writes |
|---|---|---|
license active | Active | allowed |
license expired — grace period (writes warn) | Grace | allowed |
license expired past grace (read-only) | ReadOnly | refused |
no license file present (read-only) | ReadOnly | refused |
license invalid or forged (read-only) | ReadOnly | refused |
license bound to a different machine (read-only) | ReadOnly | refused |
clock rollback detected (read-only) | ReadOnly | refused |
build newer than licensed upgrade window (read-only) | ReadOnly | refused |
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.
What clients see when writes are gated
Section titled “What clients see when writes are gated”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 validlicense 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.
Behaviour over time
Section titled “Behaviour over time”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.
Troubleshooting
Section titled “Troubleshooting”| Symptom | Cause | Fix |
|---|---|---|
Banner says no license file present | File is not at the resolved path — commonly placed next to the binary | Put it at /etc/aetherius/license.key, or set --license-file / AETHERIUS_LICENSE_FILE |
verify-license exits 2 | Unreadable — missing file, or the daemon’s service user cannot read it | Check the path and 0644 permissions |
verify-license exits 1 | Signature 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 token | Confirm which keypair the build was cut against; re-request the key if it genuinely does not match |
| Writes stopped right after an upgrade | Build is newer than the token’s upgrade window | Downgrade, or obtain a license covering the new build |
Banner says bound to a different machine | The key was issued for another host’s fingerprint, or the OS was reinstalled | Run aetheriusd fingerprint on this host and request a key bound to it, or an unbound key |
--enable-htap / AETHERIUS_CLUSTER_MODE / multi-tenancy do nothing | License-only feature with no grant in the key | Check the license features: banner line; obtain a key granting htap / cluster / multi_tenancy |
| Writes stopped after a host clock change or snapshot restore | Rollback defence tripped | Correct the system clock; the high-water-mark lives in the data dir |
INSERT fails but SELECT/DELETE work | Size cap reached | Delete 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.