Apinizer Version Upgrade
Update Methods
Apinizer version upgrade operations can be performed using two different methods depending on whether your deployment has internet access:
Used when your infrastructure has internet access. Docker images are pulled directly from Docker Hub and automatically updated. Provides a faster and easier update process.
When to Use:
- If Kubernetes worker servers can access the internet
- If Docker / Virtual Server hosts have outbound internet access
- If you want to perform a quick and easy update
- If you don't want to take extra steps for image transfer
Used when your infrastructure cannot access the internet or direct access is restricted due to security policies. Images are first pulled on a server with internet access, saved as .tar files, or uploaded to a local registry.
When to Use:
- If Kubernetes worker servers cannot access the internet
- If direct internet access is restricted due to security policies
- If a local Docker registry (Nexus, Harbor, etc.) is used
Methods:
- Manual Image Transfer (Docker/Containerd)
- Local Registry Usage
Reviewing release notes is recommended before upgrading.
Take the MongoDB backup in step 1 before you start. The first Manager start on this version runs an automatic identity and limit migration before it accepts any requests — installation-wide, no operator action needed. A few thousand records typically take minutes, so the first boot after this upgrade can run longer than the usual 30–90 seconds; watch the Manager (Mongock migration) log rather than assuming it has hung. On an installation with a large apinizer_token collection, the same boot also backfills a digest for every stored token and builds the indexes that speed up future reads (see Token Service) — first boot can take noticeably longer still on a token history in the millions.
The migration writes two ledger collections, api_client_migration_run and api_client_migration_row, and installs a daily reconcile job (03:45) that keeps retrying any record that did not converge on the first pass. Every Request Rate counter it creates — quota and throttling — starts at zero; a migrated AI Token Limit assignment is the one exception, since it is counted under the same counter its legacy budget already used, so in-window AI consumption carries over rather than resetting. This migration cannot be rolled back: the MongoDB backup in step 1 below is your only way back if something looks wrong afterward.
The same upgrade moves every enabled AI token budget on an API Proxy ACL/API Proxy Group ACL row into a typed AI Token Limit assignment — see AI Budgets — and, together with this, typed AI Token Limit assignments at every subject level start enforcing for real: the shadow-comparison mechanism (apinizer.limit.shadow.enabled and its comparison metric) is removed entirely, not only turned off. Review your existing typed AI Token Limit assignments beforehand if you are not ready for them to start blocking traffic. Version 2026.10.0 later removed the Token Quotas screen and the remaining entity budgets without converting them; see Removed AI Budgets.
Upgrade every gateway to this version within 7 days of this migration. Legacy password copies are removed only after that window (the daily reconcile job does it, not the boot-time migration itself; configurable with -Dapinizer.migration.legacyPasswordUnsetGraceDays=N) — an older-version gateway pod restarting after its window has elapsed can no longer find the password it needs to verify a migrated Consumer. See Automatic Migration at Upgrade → Legacy password cleanup for detail.
The same upgrade also retires the Rate Limit Control List and the API Proxy ACL/API Proxy Group ACL throttling/quota fields — see Legacy Limits Migrated at Upgrade for what happens to them, and Automatic Migration at Upgrade for the full step-by-step.
This version also moves OAuth2 access and refresh tokens to digest-only storage — see Token Service for what changes. The same boot-time step above backfills any missing digest and then removes the old plain-text columns; no separate action is needed. For this specific change, upgrade Gateway (Worker) nodes before the Manager: if an older Worker is still writing the old plain-text columns against an already-upgraded Manager, those columns are simply unused until the next cleanup pass — not a security exposure, just temporary extra storage.
This version also introduces Legal Holds and Data Lifecycle Purge. The upgrade adds the new Data Lifecycle permission category and its three new collections (legal holds, purge runs, purge run issues); your existing data is otherwise untouched. The new permission is granted automatically only to the Project Owner role — no other predefined role gains the ability to place a legal hold or run a purge, so no existing user unexpectedly gains the ability to permanently erase data. A dedicated Lifecycle Purge Run History retention setting is added alongside the other Log Retention entries, disabled by default. Elasticsearch API traffic logs are not rewritten by this feature in either direction — see Legal Holds and Data Lifecycle Purge → Data Subject Erasure for how they age out instead.
A defect in how a Consumer's deployed IP restriction list was assembled from its global and environment-level entries meant the list a worker actually enforced could only ever grow, never shrink, across redeploys — this is fixed in this version, and the merged list is now recomputed fresh on every deploy. If any of your consumers use IP-based access restriction, review their configured IP lists after upgrading: an address no longer present in your configuration but still being accepted before this fix stops being accepted once the fix takes effect.
An LDAP account that does not yet record which directory it came from is no longer signed in while any configured LDAP connection is disabled. Before this version such an account was resolved against the enabled connections only, which could bind it permanently to the wrong directory and let a directory you had deliberately disabled keep signing its users in. If your configuration still holds a disabled LDAP connection, enable it or delete it — one action for the whole installation — or open and save each affected user once so the account records its own connection. Accounts that already record their LDAP connection are unaffected, and a refused sign-in is written to Login Records with its reason.
This version installs an index that makes usernames (login) unique regardless of letter case. Before you upgrade, after taking the MongoDB backup from step 1 below, run this query on the MongoDB server to check your existing users for a pair that differs only by letter case:
db.user.aggregate(
[
{ $match: { login: { $type: "string" } } },
{ $group: { _id: "$login", count: { $sum: 1 }, logins: { $push: "$login" } } },
{ $match: { count: { $gt: 1 } } }
],
{ collation: { locale: "en", strength: 2 } }
)
If it returns nothing, no action is needed. If it returns one or more groups, rename the accounts from the Users screen, or delete the redundant one, before you upgrade, so only one username remains per group.
If this step is skipped: the Manager still starts, and your existing users keep signing in normally — only the index is not installed, and a warning is written to the log. But until the index is installed, a new LDAP user is refused first-time automatic account creation (LDAP users whose account already exists are unaffected). So the Manager starting cleanly is not proof the index is installed: after upgrading, search the Manager log for the line tagged 202609-006722 — it ends with "installed/verified" if the index is in place, or "NOT installed" if it is not; in the latter case, remove the duplicates with the query above and restart the Manager, which retries this step automatically on every boot.
If your installation sends Audit Records or Login Records to a relational database via the SQL/JDBC connector, run the Audit and Login Table ALTER Scripts against that database before you upgrade — not "before or during", because the insert this version issues against those two tables is unconditional. Until the script runs, every Audit Event row fails to write (though it still reaches your configured failover connector), and every Login Log row fails to write with no failover — it is dropped. This step does not apply if you use the Elasticsearch or MongoDB connector for these two log types.
If your installation writes API proxy traffic logs to a relational database via the SQL/JDBC connector, run the ALTER TABLE scripts for your starting version (see the column-count table on Table Creation Commands), before you upgrade the gateway. Do not run a script twice:
- 2026.09.0 — Log Table ALTER Scripts
- 2026.09.1 — Log Table ALTER Scripts
- 2026.09.2 — Log Table ALTER Scripts
- 2026.10.0 — Log Table ALTER Scripts
The gateway INSERT names every column of log_ApiProxyTraffic. If a column is missing, the insert of that traffic row fails and the record is lost. Which scripts apply to your starting version is listed on Table Creation Commands for Apinizer Logs. This step does not apply if you write traffic logs only to Elasticsearch or MongoDB.
This version removes the typed access model: the access entitlements and the API client authorization restrictions. Access is defined only on the Access Control List (ACL). Nothing is carried over from the removed data, because it only mirrored the ACL. Take the MongoDB backup in step 1 before you start. The first Manager start on this version runs a one-time migration that deletes the related dispatch and change-candidate records and drops the access_entitlement and api_client_authorization_restriction collections. There is no switch and no rollback path.
Follow this order:
- Stop the Manager and start it on the new version. The migration runs at this start.
- Upgrade all Workers. A restart empties their memory, and the new Worker has no typed access code.
- Make ACL changes — on the Access Control screen, by cancelling a portal subscription, or through APIops — only after the last old Worker is gone. An old Worker still holds the typed grants in memory and could keep allowing a request whose ACL row you removed.
This order applies to the move onto 2026.10.0. Notices for earlier versions above keep their own order. See Authorization of an API Client for the gateway rule.
1) Take a MongoDB Backup
MongoDB backup is taken before the update operation to prevent data loss. This command is run on the MongoDB server.
sudo mongodump \
--host <PRIMARY_MONGODB_IP_ADDRESS> \
--port=25080 \
--username=apinizer \
--password=<PASSWORD> \
--authenticationDatabase=admin \
--gzip \
--archive=<BACKUP_DIRECTORY>/apinizer-backup--<CURRENT_VERSION>--<BACKUP_DATE>--01.archive
--host(string)requiredPrimary MongoDB server IP address
--port(number)MongoDB port number
--username(string)requiredMongoDB username
--password(string)requiredMongoDB password
--authenticationDatabase(string)Authentication database
--gzip(boolean)Compresses the backup file
--archive(string)requiredPath and filename where the backup file will be saved
For detailed information about backup, you can check the Backup page.
2) Updating Apinizer Applications
The system basically consists of apimanager (manager in versions 2025.11.0 and earlier), worker, and cache applications. Depending on the license scope, integration and apiportal (portal in versions 2025.04.5 and earlier) applications may also be present.
Current version information can be accessed from Docker Hub or from the release notes page.
Update Strategy and Downtime Risk
The risk of traffic interruption during update may vary depending on factors such as pod count, update strategy, and adequacy of server resources.
If the application to be updated is running on only 1 pod, a short interruption may occur. It is recommended that the Api Manager component runs with 1 pod.
Unless a special strategy is specified during installation, updates are performed using the RollingUpdate method with at least one pod remaining active. Recreate strategy can also be preferred for Api Manager and Cache components.
In environments where the number of Kubernetes worker servers is low and existing resources are used at the limit, manual intervention may be required during update and traffic flow interruption is likely.
Pick the tab matching your installation type.
- Kubernetes
- Helm
- Docker
- Virtual Server
2.1) Online Update
2.1.1) Apinizer Api Manager Update
Apinizer Api Manager must be updated before updating other Apinizer components.
After Api Manager makes updates to the database, other Apinizer applications need to be fed from the database with current settings.
Therefore, after Api Manager is updated, make sure that Api Manager pods on Kubernetes are in "ready" status and then update other components.
Commands in this and subsequent steps are run on servers with Kubernetes Control Plane task.
kubectl get deployments -Ao wide
kubectl set image deployment/<MANAGER_DEPLOYMENT_NAME> -n <MANAGER_NAMESPACE> <MANAGER_CONTAINER_NAME>=apinizercloud/apimanager:<NEW_VERSION>
Wait for the pod to be READY, monitor pod status and logs:
kubectl get pods -n <MANAGER_NAMESPACE>
kubectl get logs -f -n <MANAGER_NAMESPACE> <POD_NAME>
2.1.2) Apinizer Worker and Cache Update
After ensuring that the Apinizer Api Manager image is updated, Apinizer Worker and Cache applications are updated.
kubectl set image deployment/<WORKER_DEPLOYMENT_NAME> -n <WORKER_CACHE_NAMESPACE> <WORKER_CONTAINER_NAME>=apinizercloud/worker:<NEW_VERSION>
kubectl set image deployment/<CACHE_DEPLOYMENT_NAME> -n <WORKER_CACHE_NAMESPACE> <CACHE_CONTAINER_NAME>=apinizercloud/cache:<NEW_VERSION>
Wait for pods to be READY, monitor pod status:
kubectl get pods -n <WORKER_CACHE_NAMESPACE>
kubectl get logs -f -n <WORKER_CACHE_NAMESPACE> <POD_NAME>
2.1.3) Apinizer Portal and Integration Update
Apinizer Portal and Integration can be updated similarly.
kubectl set image deployment/<PORTAL_DEPLOYMENT_NAME> -n <PORTAL_NAMESPACE> <PORTAL_CONTAINER_NAME>=apinizercloud/apiportal:<NEW_VERSION>
kubectl set image deployment/<INTEGRATION_DEPLOYMENT_NAME> -n <INTEGRATION_NAMESPACE> <INTEGRATION_CONTAINER_NAME>=apinizercloud/integration:<NEW_VERSION>
Wait for pods to be READY, monitor pod statuses:
kubectl get pods -n <PORTAL_NAMESPACE>
kubectl get logs -f -n <PORTAL_NAMESPACE> <POD_NAME>
kubectl get pods -n <INTEGRATION_NAMESPACE>
kubectl get logs -f -n <INTEGRATION_NAMESPACE> <POD_NAME>
2.2) Offline Update
For offline systems that require updates in Kubernetes environments, two main methods can be used:
Pulling image files to a server with internet and docker/containerd application and transferring these image files to the target Kubernetes cluster.
Using a repository application that the Kubernetes cluster will use (Nexus, Harbor, etc.).
2.2.1) Pulling Images from Online Server and Transferring to Offline Servers
If there is a machine with internet access and access to offline machines, the following steps can be performed.
2.2.1.1) Docker Usage
# All images required for upgrade are pulled from online server
docker pull apinizercloud/apimanager:<NEW_VERSION>
docker pull apinizercloud/worker:<NEW_VERSION>
docker pull apinizercloud/cache:<NEW_VERSION>
docker pull apinizercloud/apiportal:<NEW_VERSION>
docker pull apinizercloud/integration:<NEW_VERSION>
# To transfer relevant images to offline servers, images are saved in `.tar` format on online server
docker save apinizercloud/apimanager:<NEW_VERSION> -o apinizercloud-apimanager.<NEW_VERSION>.tar
docker save apinizercloud/worker:<NEW_VERSION> -o apinizercloud-worker.<NEW_VERSION>.tar
docker save apinizercloud/cache:<NEW_VERSION> -o apinizercloud-cache.<NEW_VERSION>.tar
docker save apinizercloud/apiportal:<NEW_VERSION> -o apinizercloud-apiportal.<NEW_VERSION>.tar
docker save apinizercloud/integration:<NEW_VERSION> -o apinizercloud-integration.<NEW_VERSION>.tar
# Each image is transferred to offline server
scp apinizercloud-*.tar <OFFLINE_MACHINE_USER>@<OFFLINE_MACHINE_IP>:<TARGET_DIRECTORY>
# Images are loaded on each offline server
docker load -i apinizercloud-apimanager.<NEW_VERSION>.tar
docker load -i apinizercloud-worker.<NEW_VERSION>.tar
docker load -i apinizercloud-cache.<NEW_VERSION>.tar
docker load -i apinizercloud-portal.<NEW_VERSION>.tar
docker load -i apinizercloud-integration.<NEW_VERSION>.tar
2.2.1.2) Containerd Usage
# All images required for upgrade are pulled from online server
ctr image pull docker.io/apinizercloud/apimanager:<NEW_VERSION>
ctr image pull docker.io/apinizercloud/worker:<NEW_VERSION>
ctr image pull docker.io/apinizercloud/cache:<NEW_VERSION>
ctr image pull docker.io/apinizercloud/apiportal:<NEW_VERSION>
ctr image pull docker.io/apinizercloud/integration:<NEW_VERSION>
# To transfer relevant images to offline servers, images are saved in `.tar` format on online server
ctr images export apinizercloud-apimanager.tar docker.io/apinizercloud/apimanager:<NEW_VERSION>
ctr images export apinizercloud-worker.tar docker.io/apinizercloud/worker:<NEW_VERSION>
ctr images export apinizercloud-cache.tar docker.io/apinizercloud/cache:<NEW_VERSION>
ctr images export apinizercloud-apiportal.tar docker.io/apinizercloud/apiportal:<NEW_VERSION>
ctr images export apinizercloud-integration.tar docker.io/apinizercloud/integration:<NEW_VERSION>
# Each image is transferred to offline kubernetes worker servers
scp docker.io-apinizercloud-*.tar <OFFLINE_MACHINE_USER>@<OFFLINE_MACHINE_IP>:<TARGET_DIRECTORY>
# Images are loaded on each offline server
ctr images import apinizercloud-apimanager.tar
ctr images import apinizercloud-worker.tar
ctr images import apinizercloud-cache.tar
ctr images import apinizercloud-apiportal.tar
ctr images import apinizercloud-integration.tar
2.2.2) Using Local Image Registry or Repository
Although different image registries and repositories work with different methods, in most of them, pulled images must be tagged and sent to the application.
For node configuration and deployment image path updates with corporate registries such as Nexus or Harbor, see the Container Registry section. The steps below cover the scenario of pushing images to a registry.
If the application is used as a reverse proxy, it is sufficient to provide the necessary definition for the apinizercloud repo at hub.docker.com.
2.2.2.1) Docker Usage
# All required images are pulled
docker pull apinizercloud/apimanager:<NEW_VERSION>
docker pull apinizercloud/worker:<NEW_VERSION>
docker pull apinizercloud/cache:<NEW_VERSION>
docker pull apinizercloud/apiportal:<NEW_VERSION>
docker pull apinizercloud/integration:<NEW_VERSION>
# Pulled images are retagged with necessary tag information
docker tag apinizercloud/apimanager:<NEW_VERSION> <LOCAL_REGISTRY>/apinizercloud/apimanager:<NEW_VERSION>
docker tag apinizercloud/worker:<NEW_VERSION> <LOCAL_REGISTRY>/apinizercloud/worker:<NEW_VERSION>
docker tag apinizercloud/cache:<NEW_VERSION> <LOCAL_REGISTRY>/apinizercloud/cache:<NEW_VERSION>
docker tag apinizercloud/apiportal:<NEW_VERSION> <LOCAL_REGISTRY>/apinizercloud/apiportal:<NEW_VERSION>
docker tag apinizercloud/integration:<NEW_VERSION> <LOCAL_REGISTRY>/apinizercloud/integration:<NEW_VERSION>
# Images are transferred to organization's local image registry:
docker push <LOCAL_REGISTRY>/apinizercloud/apimanager:<NEW_VERSION>
docker push <LOCAL_REGISTRY>/apinizercloud/worker:<NEW_VERSION>
docker push <LOCAL_REGISTRY>/apinizercloud/cache:<NEW_VERSION>
docker push <LOCAL_REGISTRY>/apinizercloud/apiportal:<NEW_VERSION>
docker push <LOCAL_REGISTRY>/apinizercloud/integration:<NEW_VERSION>
2.2.2.2) Containerd Usage
# All required images are pulled
ctr image pull docker.io/apinizercloud/apimanager:<NEW_VERSION>
ctr image pull docker.io/apinizercloud/worker:<NEW_VERSION>
ctr image pull docker.io/apinizercloud/cache:<NEW_VERSION>
ctr image pull docker.io/apinizercloud/apiportal:<NEW_VERSION>
ctr image pull docker.io/apinizercloud/integration:<NEW_VERSION>
# Pulled images are retagged with necessary tag information
ctr image tag docker.io/apinizercloud/apimanager:<NEW_VERSION> <LOCAL_REGISTRY>/apinizercloud/apimanager:<NEW_VERSION>
ctr image tag docker.io/apinizercloud/worker:<NEW_VERSION> <LOCAL_REGISTRY>/apinizercloud/worker:<NEW_VERSION>
ctr image tag docker.io/apinizercloud/cache:<NEW_VERSION> <LOCAL_REGISTRY>/apinizercloud/cache:<NEW_VERSION>
ctr image tag docker.io/apinizercloud/apiportal:<NEW_VERSION> <LOCAL_REGISTRY>/apinizercloud/apiportal:<NEW_VERSION>
ctr image tag docker.io/apinizercloud/integration:<NEW_VERSION> <LOCAL_REGISTRY>/apinizercloud/integration:<NEW_VERSION>
# Images are transferred to organization's local image registry:
ctr images push <LOCAL_REGISTRY>/apinizercloud/apimanager:<NEW_VERSION>
ctr images push <LOCAL_REGISTRY>/apinizercloud/worker:<NEW_VERSION>
ctr images push <LOCAL_REGISTRY>/apinizercloud/cache:<NEW_VERSION>
ctr images push <LOCAL_REGISTRY>/apinizercloud/apiportal:<NEW_VERSION>
ctr images push <LOCAL_REGISTRY>/apinizercloud/integration:<NEW_VERSION>
2.2.3) Apinizer Api Manager Update
Apinizer Api Manager must be updated before updating other Apinizer components.
After Api Manager makes updates to the database, other Apinizer applications need to be fed from the database with current settings.
Therefore, after Api Manager is updated, make sure that Api Manager pods on Kubernetes are in "ready" status and then update other components.
Commands in this and subsequent steps are run on servers with Kubernetes Control Plane task.
kubectl get deployments -Ao wide
kubectl set image deployment/<MANAGER_DEPLOYMENT_NAME> -n <MANAGER_NAMESPACE> <MANAGER_CONTAINER_NAME>=<LOCAL_REGISTRY>/apinizercloud/apimanager:<NEW_VERSION>
Wait for the pod to be READY, monitor pod status:
kubectl get pods -n <MANAGER_NAMESPACE>
kubectl logs -f -n <MANAGER_NAMESPACE> <POD_NAME>
2.2.4) Apinizer Worker and Cache Update
After ensuring that the Apinizer Api Manager image is updated, Apinizer Worker and Cache applications are updated.
kubectl set image deployment/<WORKER_DEPLOYMENT_NAME> -n <WORKER_CACHE_NAMESPACE> <WORKER_CONTAINER_NAME>=<LOCAL_REGISTRY>/apinizercloud/worker:<NEW_VERSION>
kubectl set image deployment/<CACHE_DEPLOYMENT_NAME> -n <WORKER_CACHE_NAMESPACE> <CACHE_CONTAINER_NAME>=<LOCAL_REGISTRY>/apinizercloud/cache:<NEW_VERSION>
Wait for pods to be READY, monitor pod status:
kubectl get pods -n <WORKER_CACHE_NAMESPACE>
kubectl logs -f -n <WORKER_CACHE_NAMESPACE> <POD_NAME>
2.2.5) Apinizer Portal and Integration Update
Apinizer Portal and Integration can be updated similarly.
kubectl set image deployment/<PORTAL_DEPLOYMENT_NAME> -n <PORTAL_NAMESPACE> <PORTAL_CONTAINER_NAME>=<LOCAL_REGISTRY>/apinizercloud/apiportal:<NEW_VERSION>
kubectl set image deployment/<INTEGRATION_DEPLOYMENT_NAME> -n <INTEGRATION_NAMESPACE> <INTEGRATION_CONTAINER_NAME>=<LOCAL_REGISTRY>/apinizercloud/integration:<NEW_VERSION>
Wait for pods to be READY, monitor pod statuses:
kubectl get pods -n <PORTAL_NAMESPACE>
kubectl get logs -f -n <PORTAL_NAMESPACE> <POD_NAME>
kubectl get pods -n <INTEGRATION_NAMESPACE>
kubectl get logs -f -n <INTEGRATION_NAMESPACE> <POD_NAME>
Helm-installed Apinizer modules are upgraded with helm upgrade. In this flow only the image version (image.tag) changes; all other values are preserved from the existing release via --reuse-values.
API Manager must be upgraded before the other components. API Manager runs the database (Mongock) migrations; upgrade the other modules only after its pods are Ready.
2.1) Online Update (Helm)
The chart and version (--version 1.0.0) stay the same for each module; only the new image tag is provided:
Charts before 1.0.0 created the Secret themselves; the 1.0.0 chart has none. A direct helm upgrade may let Helm delete the Secret it created, and the pods lose their MongoDB connection. Before upgrading, apply a "keep" policy to the Secret:
kubectl -n <API-Manager-Namespace> annotate secret mongo-db-credentials \
helm.sh/resource-policy=keep --overwrite
Repeat this for any other namespaces sharing the Secret and for the Portal Secret (apinizer-portal).
helm upgrade apimanager oci://registry-1.docker.io/apinizercloud/apinizer-apimanager \
--version 1.0.0 --reuse-values \
-n <API-Manager-Namespace> \
--set image.tag="<NEW_VERSION>"
Wait until the pods are Ready:
kubectl -n <API-Manager-Namespace> rollout status deploy/apimanager
helm upgrade worker oci://registry-1.docker.io/apinizercloud/apinizer-worker \
--version 1.0.0 --reuse-values -n <Worker-Namespace> --set image.tag="<NEW_VERSION>"
helm upgrade cache oci://registry-1.docker.io/apinizercloud/apinizer-cache \
--version 1.0.0 --reuse-values -n <Cache-Namespace> --set image.tag="<NEW_VERSION>"
helm upgrade integration oci://registry-1.docker.io/apinizercloud/apinizer-integration \
--version 1.0.0 --reuse-values -n <Integration-Namespace> --set image.tag="<NEW_VERSION>"
helm upgrade portal oci://registry-1.docker.io/apinizercloud/apinizer-apiportal \
--version 1.0.0 --reuse-values -n <API-Portal-Namespace> --set image.tag="<NEW_VERSION>"
--reuse-values keeps all values of the existing release; --set image.tag changes only the image version. Release names and namespaces must match the installation (each module in the namespace you used at install time).
2.1.1) Update with values.yaml (GitOps)
If you keep values.yaml under version control (e.g. GitLab), you can update from the file instead of --set: write the new image version into the image.tag field of values.yaml, commit it, then run helm upgrade -f with the same file.
helm upgrade apimanager oci://registry-1.docker.io/apinizercloud/apinizer-apimanager \
--version 1.0.0 \
-n <API-Manager-Namespace> \
-f apinizer-apimanager/values.yaml
For the other modules use the corresponding chart and values.yaml path (apinizer-worker, apinizer-cache, apinizer-integration, apinizer-apiportal).
Do not use --reuse-values together with -f values.yaml; the file is the single source of values. The Secret is still out of scope — never put credentials in values.yaml.
2.2) Verification
helm list -n <NAMESPACE> # repeat for each module's namespace
kubectl -n <NAMESPACE> get pods
2.3) Offline / Local Registry
If the cluster has no internet access, images are moved to a local registry (see the offline image-transfer steps in the Kubernetes tab above). When using a local registry, provide the repository together with the image tag:
helm upgrade apimanager oci://registry-1.docker.io/apinizercloud/apinizer-apimanager \
--version 1.0.0 --reuse-values -n <API-Manager-Namespace> \
--set image.repository=<LOCAL_REGISTRY>/apinizercloud/apimanager \
--set image.tag="<NEW_VERSION>"
2.4) Rollback (Helm Rollback)
Helm stores every upgrade as a revision; you can return to a previous revision if needed:
helm history apimanager -n <API-Manager-Namespace>
helm rollback apimanager <REVISION> -n <API-Manager-Namespace>
kubectl -n <API-Manager-Namespace> rollout status deploy/apimanager
Mongock migrations are forward-only. If the new version changed the DB schema, a rollback may prevent the old Manager from booting; always back up MongoDB before major upgrades (see section 1) and, if needed, apply the restore steps in section 3.
Apinizer Docker images are immutable — to move to a new version, pull the new tag and recreate the container. Some modules (Cache, Integration, Worker) are stateful and need a rolling-upgrade pattern.
For the version strategy: Docker Overview — tag convention
2.1) Quick Reference
NEW=2026.04.6
docker pull apinizercloud/<module>:${NEW}
# docker-compose:
# 1) update the image tag in compose.yml
# 2) docker compose up -d <service>
# vanilla docker:
docker stop <container-name> && docker rm <container-name>
docker run -d --name <container-name> ... apinizercloud/<module>:${NEW}
2.2) Recommended Upgrade Order
- MongoDB (if required — see MongoDB Upgrade)
- API Manager — Mongock migrations run and update the schema
- Cache (rolling — one node at a time)
- Worker (rolling — one replica at a time; behind LB)
- Integration (rolling — wait for the Quartz cluster check-in cycle)
- API Portal — stateless, simple replace
2.3) Per-Module Details
API Manager
The Manager runs Mongock migrations, but you do not need to scale down to a single instance — the new Manager can start while the old one is still up. Migrations are idempotent.
docker pull apinizercloud/apimanager:${NEW}
docker compose up -d apimanager # tag bumped in compose.yml
docker compose logs -f apimanager # "Mongock finished" then "Started ApinizerManagerApp"
The first start can take 30–90 seconds for Mongock migrations.
Back up MongoDB before major version jumps. Major version chains (e.g. 2026.04.x → 2026.05.x → 2026.06.x) must be stepped through one at a time, watching Mongock logs at each step.
Cache (rolling upgrade)
Cache nodes form a Hazelcast cluster — upgrade one node at a time:
docker pull apinizercloud/cache:${NEW}
# Node 1
docker stop -t 30 apinizer-cache-1 && docker rm apinizer-cache-1
docker run -d --name apinizer-cache-1 ... apinizercloud/cache:${NEW}
# Wait for 'Members {size:3, ver:N}' to appear again
docker logs apinizer-cache-1 | grep -E 'Members \{'
# Then node 2, then node 3...
The cluster keeps serving with one node missing (replication factor ≥ 1).
Worker
For Workers behind a load balancer, do a canary / blue-green replace:
docker pull apinizercloud/worker:${NEW}
# Take one replica out of the LB
# Replace the container
docker stop -t 60 apinizer-worker-1 && docker rm apinizer-worker-1
docker run -d --name apinizer-worker-1 ... apinizercloud/worker:${NEW}
# Once healthy, add it back to the LB
# Roll the remaining replicas
docker stop -t 60 is required — in-flight HTTP / gRPC / WebSocket requests drain up to 60 s.
Integration (clustered Quartz)
Integration nodes form a cluster over MongoDB — while one node restarts, the others take over its triggers:
docker pull apinizercloud/integration:${NEW}
# Node 1
docker stop -t 120 apinizer-integration-1 && docker rm apinizer-integration-1
docker run -d --name apinizer-integration-1 ... apinizercloud/integration:${NEW}
# Wait for 'Quartz Scheduler Prod Environment Setup started'
# Then node 2, then node 3...
stop -t 120 is required — waitForJobsToCompleteOnShutdown=true lets in-flight jobs drain.
API Portal
Stateless — a simple recreate is enough:
docker pull apinizercloud/apiportal:${NEW}
docker compose up -d apiportal # tag bumped
For multiple replicas, replace each one in turn behind the LB.
2.4) Troubleshooting
New Manager fails to boot: Mongock lock acquired by another instance
The old Manager was SIGKILLed before releasing the Mongock lock. In the Manager DB:
use apinizer
db.mongockLock.deleteMany({})
After clearing the lock, restart the Manager.
Worker on the new version cannot bind to the Environment
A major version may have changed the Environment schema. Check the Manager logs and verify the Environment is on the correct schema.
image is being used by container error in compose
docker compose up -d does not recreate the container unless the tag changes. Force:
docker compose up -d --force-recreate <service>
For Linux / VM installations the upgrade flow is: download the new tarball, extract next to the existing install, copy conf/application.env and conf/master.key over, re-register the systemd unit, restart the service.
The conf/master.key file must not be lost — it is the only key that decrypts ENC(...) values. Always back it up before swapping versions.
2.1) Quick Reference
NEW=2026.04.6
sudo systemctl stop apinizer-<module>
sudo tar -xzf apinizer-<module>-${NEW}-linux-x64.tar.gz -C /opt
sudo cp /opt/apinizer-<module>/conf/application.env /opt/apinizer-<module>-${NEW}/conf/
sudo cp /opt/apinizer-<module>/conf/master.key /opt/apinizer-<module>-${NEW}/conf/
sudo chown -R apinizer:apinizer /opt/apinizer-<module>-${NEW}/conf
sudo chmod 600 /opt/apinizer-<module>-${NEW}/conf/application.env
sudo chmod 400 /opt/apinizer-<module>-${NEW}/conf/master.key
sudo mv /opt/apinizer-<module> /opt/apinizer-<module>.bak
sudo mv /opt/apinizer-<module>-${NEW} /opt/apinizer-<module>
sudo /opt/apinizer-<module>/bin/<module>-install.sh # re-register systemd unit
sudo systemctl start apinizer-<module>
sudo systemctl status apinizer-<module>
# After healthy:
sudo rm -rf /opt/apinizer-<module>.bak
2.2) Recommended Upgrade Order
- MongoDB (if required)
- API Manager — Mongock migrations
- Cache — rolling, one node at a time
- Worker — rolling behind LB
- Integration — clustered Quartz, rolling
- API Portal — stateless
2.3) Per-Module
API Manager
NEW=2026.04.6
sudo systemctl stop apinizer-apimanager
# Back up
sudo cp /opt/apinizer-manager/conf/application.env ~/manager-env-pre-${NEW}.bak
sudo cp /opt/apinizer-manager/conf/master.key ~/manager-key-pre-${NEW}.bak
# Extract new package
curl -fSLO "https://packages.apinizer.com/apinizer-packages/releases/apimanager/${NEW}/apinizer-apimanager-${NEW}-linux-x64.tar.gz"
sudo tar -xzf apinizer-apimanager-${NEW}-linux-x64.tar.gz -C /opt
# Move config
sudo cp /opt/apinizer-manager/conf/application.env /opt/apinizer-apimanager-${NEW}/conf/
sudo cp /opt/apinizer-manager/conf/master.key /opt/apinizer-apimanager-${NEW}/conf/
sudo chown -R apinizer:apinizer /opt/apinizer-apimanager-${NEW}/conf
sudo chmod 600 /opt/apinizer-apimanager-${NEW}/conf/application.env
sudo chmod 400 /opt/apinizer-apimanager-${NEW}/conf/master.key
# Swap + reinstall
sudo mv /opt/apinizer-manager /opt/apinizer-manager.bak
sudo mv /opt/apinizer-apimanager-${NEW} /opt/apinizer-manager
sudo /opt/apinizer-manager/bin/apimanager-install.sh
sudo systemctl start apinizer-apimanager
sudo journalctl -u apinizer-apimanager -f # watch Mongock log
The first start can take 30–90 s for Mongock. After Started ApinizerManagerApp:
curl -fsS http://127.0.0.1:8080/management/health
# If healthy:
sudo rm -rf /opt/apinizer-manager.bak
Cache (rolling upgrade)
Cache nodes are stateful Hazelcast members — upgrade one at a time:
# On node 1:
sudo systemctl stop apinizer-apicache
# (same flow as Manager: extract tarball, move conf, install, start)
# Then move to node 2 — wait for 'Members {size:3, ver:N}' in the log
The cluster keeps serving while one node is missing.
Worker
Roll each replica behind the LB in turn:
# Take replica 1 out of LB
sudo systemctl stop apinizer-apiworker # SIGTERM + 60 s drain
# (tarball swap flow)
sudo systemctl start apinizer-apiworker
curl -fsS http://127.0.0.1:8091/server-status
# Healthy → add back to LB, move to replica 2
Integration
Quartz cluster check-in is 7.5 s — while one node restarts, the others take over its triggers:
sudo systemctl stop apinizer-apiintegration # SIGTERM + waitForJobsToCompleteOnShutdown drain
# (tarball swap flow)
sudo systemctl start apinizer-apiintegration
sudo journalctl -u apinizer-apiintegration -f # wait for 'Quartz Scheduler Prod Environment Setup started'
API Portal
Stateless — simple swap:
sudo systemctl stop apinizer-apiportal
# tarball swap
sudo systemctl start apinizer-apiportal
2.4) Troubleshooting
Service exits with "is not set" from the new package
The conf/application.env move step was skipped or permissions are broken. Manual check:
ls -la /opt/apinizer-<module>/conf/
# application.env must be mode 600 and owned by apinizer:apinizer
# master.key must be mode 400 and owned by apinizer:apinizer
"Master key file not found" at boot
master.key was not moved. Restore from backup:
sudo cp ~/manager-key-pre-${NEW}.bak /opt/apinizer-manager/conf/master.key
sudo chown apinizer:apinizer /opt/apinizer-manager/conf/master.key
sudo chmod 400 /opt/apinizer-manager/conf/master.key
sudo systemctl restart apinizer-apimanager
Mongock lock acquired by another instance
The previous Manager was killed before it could release the lock. In MongoDB:
use apinizer
db.mongockLock.deleteMany({})
Then restart the Manager.
3) Rolling Back Apinizer Application Updates
Version downgrade is not supported in Apinizer applications. However, if there are database backups, an updated version can be rolled back.
Once the automatic identity and limit migration described in section 1 above has run, downgrading the application alone does not undo it — an older Manager binary does not know how to read the typed records the migration wrote. The only way back is restoring the MongoDB backup taken in step 1 before the upgrade, following the steps below.
When updates need to be rolled back for any reason, the first thing to do is check that MongoDB backup was taken before the update. If there is no database backup taken before the update, there is no way to roll back the changes Api Manager application will make to the database, so if there is a system backup of the database servers, you can return to the most recent backup at that date and return to that version.
This operation will cause loss of changes made since that date, so it should be done carefully. Since structural differences may occur with the update, this operation can only be considered for reference purposes.
3.1) MongoDB Database Restore
Before this operation, it should be confirmed that the Api Manager application is not in a restart loop. For the safest method, the Api Manager application should be stopped.
- Kubernetes
- Docker
- Virtual Server
Api Manager replica count is reduced to 0 and all pods are shut down:
kubectl scale deploy <MANAGER_DEPLOYMENT_NAME> -n <MANAGER_NAMESPACE> --replicas=0
MongoDB should be returned to the most recent backup. The --drop parameter can be used to prevent possible conflicts during return. This will only drop collections that have a counterpart in the backup file and then perform the load.
docker compose down
# or: docker stop -t 60 apinizer-apimanager && docker rm apinizer-apimanager
MongoDB should be returned to the most recent backup. The --drop parameter can be used to prevent possible conflicts during return. This will only drop collections that have a counterpart in the backup file and then perform the load.
sudo systemctl stop apinizer-apimanager
MongoDB should be returned to the most recent backup. The --drop parameter can be used to prevent possible conflicts during return. This will only drop collections that have a counterpart in the backup file and then perform the load.
For detailed information, the MongoDB Database Backup and Restore page can be reviewed.
3.2) Rolling Back Api Manager Application Version
- Kubernetes
- Helm
- Docker
- Virtual Server
If a local registry will be used during rollback, commands should be updated accordingly.
kubectl set image deployment/<MANAGER_DEPLOYMENT_NAME> -n <MANAGER_NAMESPACE> <MANAGER_CONTAINER_NAME>=apinizercloud/apimanager:<OLD_VERSION>
kubectl scale deploy <MANAGER_DEPLOYMENT_NAME> -n <MANAGER_NAMESPACE> --replicas=1
Wait for the pod to be READY, monitor pod status and logs:
kubectl get pods -n <MANAGER_NAMESPACE>
kubectl logs -f -n <MANAGER_NAMESPACE> <POD_NAME>
Helm stores every upgrade as a revision; use helm history to pick the target revision and roll back to it:
helm history apimanager -n <API-Manager-Namespace>
helm rollback apimanager <REVISION> -n <API-Manager-Namespace>
Wait for the pod to be Ready:
kubectl -n <API-Manager-Namespace> rollout status deploy/apimanager
kubectl -n <API-Manager-Namespace> get pods
docker compose down
# or: docker stop -t 60 apinizer-apimanager && docker rm apinizer-apimanager
Update the image tag for the Manager service in your docker-compose.yml file to the previous version.
docker compose up -d apimanager
docker compose logs -f apimanager
sudo systemctl stop apinizer-apimanager
sudo mv /opt/apinizer-manager /opt/apinizer-manager.failed
sudo mv /opt/apinizer-manager.bak /opt/apinizer-manager
sudo /opt/apinizer-manager/bin/apimanager-install.sh
sudo systemctl start apinizer-apimanager
sudo systemctl status apinizer-apimanager
3.3) Rolling Back Other Applications' Versions
When the Api Manager application is running, other applications can be rolled back to the old version together.
- Kubernetes
- Helm
- Docker
- Virtual Server
If a local registry will be used during rollback, commands should be updated accordingly.
kubectl set image deployment/<WORKER_DEPLOYMENT_NAME> -n <WORKER_CACHE_NAMESPACE> <WORKER_CONTAINER_NAME>=apinizercloud/worker:<OLD_VERSION>
kubectl set image deployment/<CACHE_DEPLOYMENT_NAME> -n <WORKER_CACHE_NAMESPACE> <CACHE_CONTAINER_NAME>=apinizercloud/cache:<OLD_VERSION>
kubectl set image deployment/<PORTAL_DEPLOYMENT_NAME> -n <PORTAL_NAMESPACE> <PORTAL_CONTAINER_NAME>=apinizercloud/apiportal:<OLD_VERSION>
kubectl set image deployment/<INTEGRATION_DEPLOYMENT_NAME> -n <INTEGRATION_NAMESPACE> <INTEGRATION_CONTAINER_NAME>=apinizercloud/integration:<OLD_VERSION>
Wait for pods to be READY, monitor pod statuses and logs if necessary:
kubectl get pods -A
For each module, find the target revision with helm history <release> -n <namespace> and roll back:
helm rollback worker <REVISION> -n <Worker-Namespace>
helm rollback cache <REVISION> -n <Cache-Namespace>
helm rollback integration <REVISION> -n <Integration-Namespace>
helm rollback portal <REVISION> -n <API-Portal-Namespace>
kubectl get pods -A
Revert the image tags for Worker, Cache, Portal, and Integration to their previous versions.
docker compose up -d worker cache apiportal integration
docker compose logs -f
For each module (Worker, Cache, Integration, Portal):
sudo systemctl stop apinizer-<module>
sudo mv /opt/apinizer-<module> /opt/apinizer-<module>.failed
sudo mv /opt/apinizer-<module>.bak /opt/apinizer-<module>
sudo /opt/apinizer-<module>/bin/<module>-install.sh
sudo systemctl start apinizer-<module>
sudo systemctl status apinizer-apiworker
sudo systemctl status apinizer-apicache
sudo systemctl status apinizer-apiintegration
sudo systemctl status apinizer-apiportal
Mongock migrations are forward-only. If the new version changed the DB schema, rolling back may prevent the old Manager from booting. Back up MongoDB before major upgrades.