License Management
Manage your API7 Gateway license, understand the production and non-production core quotas and license states, and configure license file paths for automated deployment.
API7 Gateway requires a valid license to operate. The license controls which features are available (e.g., API Gateway, Developer Portal) and defines the maximum number of data plane CPU cores your deployment can use, split into a production and a non-production quota.
License Properties
Each license contains the following properties:
| Property | Description |
|---|---|
| Customer | Organization name |
| Effective Date | When the license becomes active |
| Expiration Date | When the license expires |
| Max DP Cores | Maximum total CPU cores across data plane instances in production gateway groups |
| Max Non-production DP Cores | Maximum total CPU cores across data plane instances in non-production gateway groups. Available in API7 Enterprise from version 3.10.5. |
| Feature List | Licensed features (e.g., API7 Gateway, API7 Portal) |
| Deployment ID | Ties the license to a specific deployment |
| Free Trial | Whether this is a trial license |
Upload a License
Using the Dashboard
- Log in to the API7 Dashboard.
- If no license is active, you are prompted to upload one on login.
- Upload the license file and click Activate.
Using the Admin API
Upload a license via the Admin API:
If you are not running locally, replace localhost with your Dashboard or Admin API host.
curl -k "https://localhost:7443/api/license" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"data": "<LICENSE_CONTENT>"
}'The licence file is multi-line PEM, so it has to be JSON-encoded before it goes into data. Let jq do it rather than escaping by hand:
curl -k "https://localhost:7443/api/license" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d "$(jq -Rs '{data: .}' < api7-ee-license)"You can validate a license without applying it by adding the ?dry-run=all query parameter:
curl -k "https://localhost:7443/api/license?dry-run=all" -X PUT \
-H "X-API-KEY: ${API_KEY}" \
-H "Content-Type: application/json" \
-d '{
"data": "<LICENSE_CONTENT>"
}'Using a License File Path
For automated deployments (e.g., Kubernetes), you can configure the control plane to load the license from a file. The system polls the file every 5 seconds for changes.
Configure the license file path in the control plane's configuration:
dashboard_configuration:
license:
file_path: "/path/to/license.txt"This approach is useful for GitOps workflows where the license is stored as a Kubernetes Secret and mounted into the control plane pod.
Retrieve License Details
Get the current license details, including the runtime status:
curl -k "https://localhost:7443/api/license" \
-H "X-API-KEY: ${API_KEY}"The response includes the license properties and the current runtime status.
Core Quota
A license carries two independent core quotas:
| Quota | Covers | License property |
|---|---|---|
| Production | Data plane instances in gateway groups whose environment is production | max_dp_cores |
| Non-production | Data plane instances in gateway groups whose environment is non_production | max_non_production_dp_cores |
Every gateway group belongs to exactly one of the two, so a staging or testing gateway group does not consume production cores. See Gateway Groups for how to set the environment. Gateway groups created before version 3.10.5 count as production.
A license issued before version 3.10.5 carries no non-production quota, which reads as 0. Such a license behaves exactly as it did before as long as every gateway group stays production; to run non-production gateway groups, request a license that grants non-production cores.
How Core Usage Is Tracked
At midnight each day, the control plane measures the peak core usage from the previous day separately for each quota, and compares each against the matching licensed value.
How Gateway Worker Processes Affect Licensed Cores
The max_dp_cores property in an API7 license defines the maximum permitted DP core usage for production gateway groups. The max_non_production_dp_cores property defines the separate maximum for non-production gateway groups. Both quotas use the same accounting method.
At runtime, DP core usage is calculated from the effective number of NGINX worker processes in each gateway data plane instance. It is not calculated directly from Kubernetes apisix.resources.requests.cpu, apisix.resources.limits.cpu, or the actual CPU utilization of a pod.
The CPU configurations in the following table illustrate the license accounting method only. They are not recommended production configurations. For performance-related configuration, follow the guidance in CPU Resources and Worker Processes.
| Running DP instances | nginx.workerProcesses | CPU request / limit | Counted DP core usage |
|---|---|---|---|
| One pod | 1 | 500m / 500m | 1 |
| One pod | 1 | 500m / 1200m | 1 |
| Two pods | 1 per pod | 500m / 500m per pod | 1 + 1 = 2 |
| Two pods | 2 and 4, respectively | Does not affect the accounting method | 2 + 4 = 6 |
Increasing a pod's CPU limit from 500m to 1200m therefore does not change its counted DP core usage if the effective worker count remains 1. CPU resource settings alone do not change the license usage to 0.5 or 1.2 DP cores.
License Runtime States
Each quota moves through three runtime states of its own, based on its own core usage:
| State | Description | Impact |
|---|---|---|
| Normal | Core usage is within the licensed limit | Full functionality |
| DP Core Exceeded | Core usage exceeds the limit; a 7-day grace period begins | Full functionality (warning only) |
| Restricted | Grace period expired with cores still exceeding the limit | Write operations are blocked; read operations continue |
Each quota enters and leaves these states on its own, driven only by its own usage. When one quota reaches the Restricted state:
- Blocked: Creating or updating services, routes, consumers, plugins, SSL certificates, and other configuration resources in the gateway groups that draw from that quota. Operations that are not scoped to a gateway group, such as managing users, roles, and portals, are governed by the production quota's runtime state, so they are blocked only when the production quota is restricted.
- Allowed: Everything in the gateway groups on the other quota, plus reading configurations, viewing dashboards, and uploading a new license.
To resolve the restricted state, either reduce the number of data plane cores in the affected gateway groups (e.g., by scaling down gateway replicas) or upload a license with a higher quota.
Troubleshooting Core Count Discrepancies
If the counted DP core usage looks higher than the number of data plane replicas you believe are running, the mismatch is usually explained by one of the following:
- The counted value is a peak, not a live reading. Core usage is evaluated once per quota as the highest hourly total observed during the previous day (see How Core Usage Is Tracked), so a short-lived spike — for example, a rolling restart or a temporary scale-up — can raise the day's counted usage even after you have scaled back down.
- A rolling restart briefly counts both the old and new instance. Each running gateway process reports its worker count to the control plane under its own instance registration. During a Kubernetes rolling update, node replacement, or any deployment strategy that starts the replacement pod before terminating the old one, the two processes can both be sending heartbeats for the same hour. That hour's total genuinely reflects two live sets of workers running concurrently, not a leftover or duplicate counted in error.
- An offline instance keeps its last hourly numbers, but stops adding new ones. An instance that stops sending heartbeats is marked as having lost connection after about 60 seconds, and as offline after about 2 hours of silence. From that point it no longer contributes to any new hour's total. However, the instance record itself — and the hourly numbers it already reported while it was still running — is not removed from the system until it has been offline for about 7 days. If you are auditing a day when an instance went offline partway through, its usage from the hours before it disconnected is still part of that day's peak.
- Scaling by adding worker processes counts the same as scaling by adding pods. As shown in How Gateway Worker Processes Affect Licensed Cores, the counted total is a sum of the effective worker count reported by every running instance, regardless of whether that count comes from more pods or from more
nginx.workerProcessesper pod. Two pods running one worker each and one pod running two workers both count as2.
If you need to reconcile the counted total against what you expect, check how many gateway instances are actually reporting to each gateway group and cross-reference their environment (production vs. non-production, see Core Quota) — a gateway group's environment determines which quota its instances draw from, and moving gateway groups between environments only affects usage recorded from that point forward, not hours already counted.
License Expiration
When a license expires:
- Read operations (viewing configurations, dashboards) continue to work.
- Write operations (creating or updating resources) are blocked.
- You can still upload a new license.
Monitor your license expiration date and plan renewals in advance. If you need a license, contact API7 sales or request a trial license.
Free Trial License
A free trial license is available for evaluation purposes:
- Maximum duration: 90 days.
- The trial period starts from the deployment date.
To request a trial license, visit api7.ai/try.