License Lifecycle
Sukko uses ECDSA P-256-signed license keys to determine which edition (Community, Pro, Enterprise) is active. License changes take effect immediately via hot-reload — no restart required for upgrades or limit changes.
How License Changes Propagate
When a license is reloaded via POST /api/v1/license:
- Provisioning validates the ECDSA P-256 signature and checks replay protection (
iatmust be newer) - New edition and limits are atomically swapped in memory
- All services (Core, Gateway, Push) receive the update via gRPC stream
- Feature gates and limits take effect immediately
No restart is needed for upgrades or downgrades. The message backend is edition-independent — Kafka runs on every edition, so an edition change never forces a backend switch.
Upgrades
Community → Pro
| What Changes | Effect |
|---|---|
| Tenant limit | 3 → 50 (new tenants can be created immediately) |
| Connection limit | 500 → 10,000 |
| Shard limit | 1 → 8 |
| Feature gates | SSE, Web Push, alerting, tracing, analytics, admin UI, token revocation, webhooks, connections API — all activate immediately. (The data path — Kafka backend, message history, gap recovery, REST publish — and per-tenant channel rules are ungated, available in every edition.) |
Community → Enterprise
Same as Community → Pro, plus:
| What Changes | Effect |
|---|---|
| All limits | Unlimited |
| Feature gates | The audit-log query API activates immediately (mobile push, FCM/APNs, is planned) |
Pro → Enterprise
| What Changes | Effect |
|---|---|
| All limits | Unlimited (was capped) |
| Feature gates | Enterprise-only features activate: the audit-log query API (mobile push, FCM/APNs, is planned) |
All upgrades are immediate. No data migration, no restart, no downtime.
Downgrades
Downgrades are graceful — existing resources are preserved, but new creation is blocked when limits are exceeded.
Enterprise → Pro
| Component | Behavior |
|---|---|
| Existing tenants | Preserved. New creation blocked if count exceeds 50. |
| Existing connections | Maintained. New connections rejected if over 10,000. |
| Mobile push (FCM/APNs, planned) | New android/ios registrations return 403 EDITION_LIMIT. Web Push continues (it is Pro). Existing device registrations preserved. |
| Audit logs | Records keep being written. Existing logs preserved. The query endpoint returns 403 EDITION_LIMIT. |
| Shards | If running >8 shards, restart required to reduce. |
Enterprise → Community
| Component | Behavior |
|---|---|
| Existing tenants | Preserved. New creation blocked if count exceeds 3. |
| Existing connections | Maintained. New connections rejected if over 500. |
| Kafka backend | Unaffected — the backend is edition-independent. Ingestion, history, and gap recovery continue. Client/REST publishes into kafka become unroutable once routing rules can no longer be managed (routing is Pro). |
| SSE transport | New SSE connections return 403 EDITION_LIMIT. Existing SSE connections maintained. |
| Per-tenant channel rules | Unaffected — channel rules are ungated (available in every edition). Existing rules keep enforcing; creation and updates remain available. |
| Push notifications | New registrations return 403 EDITION_LIMIT (Web Push requires Pro; mobile requires Enterprise). Existing registrations preserved. |
Pro → Community
Same as Enterprise → Community, except mobile push and the audit-log query API were already unavailable.
License Expiry
When a license expires, Sukko immediately degrades to Community edition. There is no grace period — at expiry time, the system behaves as if running Community.
| Scenario | Effect |
|---|---|
| Pro expires | Same as Pro → Community downgrade. Existing resources preserved, new creation blocked at Community limits. |
| Enterprise expires | Same as Enterprise → Community downgrade. The Kafka backend keeps running — ingestion is unaffected. |
Monitoring Expiry
Sukko exposes a Prometheus metric for license expiry:
sukko_license_expiry_timestamp
Set up an alert to catch upcoming expirations:
# Alert 7 days before expiry
- alert: SukkoLicenseExpiringSoon
expr: (sukko_license_expiry_timestamp - time()) < 7 * 86400
labels:
severity: warning
Key Behaviors
No forced disconnections — Sukko never drops existing WebSocket or SSE connections on downgrade or expiry. Connections established before the change continue until the client disconnects.
No data deletion — Tenants, channel rules, routing rules, audit logs, and push registrations are never deleted on downgrade. They remain in the database and become accessible again on upgrade.
Replay protection — License keys include an iat (issued-at) timestamp. Older keys are rejected to prevent replay attacks.
Checking Current Edition
Every service exposes an edition endpoint:
curl http://localhost:3000/edition # Gateway
curl http://localhost:8080/edition # Provisioning
curl http://localhost:3005/edition # Core
Or via the CLI:
sukko edition
Key rotation & versioned upgrades
Sukko's license public key is embedded in each binary, and license validation is fully offline — there is no license server to call. Two things follow for you as an operator:
- Pin an immutable version. Deploy a specific
ghcr.io/sukko-dev/sukko-*:vX.Y.Zimage tag rather than a moving tag, so you always know exactly which build you are running. - Upgrades never invalidate a license. Upgrading to a newer Sukko version never breaks an existing, valid license key — upgrade whenever suits you.
On the rare occasion Sukko rotates the license signing key, the new Sukko release embeds both the previous and new keys during an overlap window. So:
- Your existing license keeps validating after you upgrade — no coordinated cutover, no downtime.
- Once you are on the newer release, any renewed or re-issued license simply works.
The one thing to know: stay reasonably current. If you skip the overlap release entirely
and then renew your license after a rotation, the renewed key may be signed by a key your
older binary does not embed — upgrading to a current vX.Y.Z release resolves it.
Next Steps
- Upgrade to Pro — Set your license key
- Edition Comparison — Feature matrix across editions
- Configuration Reference — License-related env vars