# Upgrade KubeMQ (/deploy/upgrade)



This page upgrades a running KubeMQ installation to the latest release. When you finish, `kmq license` shows the new release in its VERSION column, the license is still active, and a test message round-trips. Time: about 15 minutes.

Commands use the default names `kubemq-operator`, `messaging`, `kubemq` and the namespace `kubemq`; use your own if they differ.

These commands are for bash on macOS and Linux. On Windows, run them in WSL (Windows Subsystem for Linux), or use the kmq tab of [Try KubeMQ](/deploy/quickstart), which runs natively on Windows.

## Before you start [#before-you-start]

1. Update kmq, the KubeMQ command-line tool:

   ```bash
   kmq update
   ```

   You should see:

   ```text title="Output"
   HARNESS_OUTPUT_PENDING
   ```

   If kmq reports `unknown command "update"`, re-run the installer from [Try KubeMQ](/deploy/quickstart#install-kmq).

2. Find what you run: the VERSION column of `kmq license` (on Kubernetes, `kmq license --kube-context YOUR_KUBE_CONTEXT`). For Helm, list the releases:

   ```bash
   helm list --kube-context YOUR_KUBE_CONTEXT -A
   ```

   Replace: `YOUR_KUBE_CONTEXT` — your cluster's kubectl context; `kubectl config get-contexts` lists them.

   If one Helm release holds both the operator and the cluster, go to [Move from the old combined chart release](#combined-release) first. Artifact names: [Requirements and supported setups](/deploy/install/requirements#artifacts-and-versions).

3. Read [Release notes](/release-notes) for each release after yours, especially "Before you upgrade".

4. Back up: on one server, steps 1 to 4 of [Back up and restore](/operate/backup-and-restore#steps).  For Kubernetes, [contact support](mailto:support@kubemq.io) before relying on a restore.

## Steps [#steps]

### Upgrade one server [#upgrade-one-server]

<Tabs groupId="install-tool" items="[&#x22;kmq&#x22;, &#x22;Docker&#x22;]">
  <Tab value="kmq">


    <Steps>
      <Step>
        #### Upgrade the server [#upgrade-the-server]



        ```bash
        kmq deploy update --installation kubemq --deadline 10m
        ```

        You should see:

        ```text title="Output"
        HARNESS_OUTPUT_PENDING
        ```

        The `kubemq-data` volume and your data stay.
      </Step>
    </Steps>
  </Tab>

  <Tab value="Docker">
    <Steps>
      <Step>
        #### Pull the latest image [#pull-the-latest-image]

        ```bash
        docker pull --platform linux/amd64 europe-docker.pkg.dev/kubemq/images/kubemq-next:latest
        ```

        You should see:

        ```text title="Output"
        HARNESS_OUTPUT_PENDING
        ```
      </Step>

      <Step>
        #### Remove the old container [#remove-the-old-container]

        ```bash
        docker stop kubemq
        ```

        ```bash
        docker rm kubemq
        ```

        Check that the volume stays:

        ```bash
        docker volume ls --filter name=kubemq-data --format '{{.Name}}'
        ```

        You should see:

        ```text title="Output"
        HARNESS_OUTPUT_PENDING
        ```
      </Step>

      <Step>
        #### Start the server again [#start-the-server-again]

        In `kubemq-private`, rerun your install command; from [Install with Docker](/deploy/install/docker), that is:

        <RunKubeMQ />

        Check that the server is running:

        ```bash
        docker ps --filter name=kubemq --format '{{.Names}}: {{.Status}}'
        ```

        You should see:

        ```text title="Output"
        HARNESS_OUTPUT_PENDING
        ```
      </Step>
    </Steps>

    With Docker Compose, run `docker compose pull`, then `docker compose up -d`. With Podman, use `podman` in place of `docker`.
  </Tab>
</Tabs>

Then check the license:

```bash
kmq license
```

You should see:

```text title="Output"
HARNESS_OUTPUT_PENDING
```

VERSION shows the new release; STATE is unchanged. If kmq cannot connect, the server is still starting: wait a few seconds and run it again. Sign in at `http://localhost:8080`: your channels are still there.

### Upgrade a Kubernetes cluster [#upgrade-a-kubernetes-cluster]

<Tabs groupId="install-tool" items="[&#x22;kmq&#x22;, &#x22;Helm&#x22;]">
  <Tab value="kmq">


    <Steps>
      <Step>
        #### Upgrade the cluster [#upgrade-the-cluster]



        ```bash
        kmq deploy update --installation messaging --deadline 20m
        ```

        You should see:

        ```text title="Output"
        HARNESS_OUTPUT_PENDING
        ```

        kmq applies the custom resource definitions first, then upgrades the operator and cluster.
      </Step>
    </Steps>
  </Tab>

  <Tab value="Helm">
    <Callout type="warn" title="Data loss: do not use --reuse-values">
      `--reuse-values` keeps the old chart's images: the servers stay on the old release, and a later rollback can meet a store it cannot read.
    </Callout>

    <Steps>
      <Step>
        #### Update the chart list [#update-the-chart-list]

        ```bash
        helm repo update kubemq-next
        ```

        You should see:

        ```text title="Output"
        HARNESS_OUTPUT_PENDING
        ```
      </Step>

      <Step>
        #### Update the custom resource definitions [#update-the-custom-resource-definitions]

        Helm never upgrades them itself.

        ```bash
        helm show crds kubemq-next/kubemq-next | kubectl --context YOUR_KUBE_CONTEXT apply --server-side --force-conflicts -f -
        ```

        You should see:

        ```text title="Output"
        HARNESS_OUTPUT_PENDING
        ```
      </Step>

      <Step>
        #### Upgrade the operator [#upgrade-the-operator]

        ```bash
        helm upgrade --install kubemq-operator kubemq-next/kubemq-next --kube-context YOUR_KUBE_CONTEXT -n kubemq \
          --set operator.enabled=true --set cluster.enabled=false --wait
        ```

        You should see:

        ```text title="Output"
        HARNESS_OUTPUT_PENDING
        ```

        The servers then restart one at a time on the release the operator sets.
      </Step>

      <Step>
        #### Upgrade the cluster [#upgrade-the-cluster-1]

        In `kubemq-private`, where `cluster-values.yaml` lives:

        ```bash
        helm upgrade --install messaging kubemq-next/kubemq-next --kube-context YOUR_KUBE_CONTEXT -n kubemq -f cluster-values.yaml
        ```

        You should see:

        ```text title="Output"
        HARNESS_OUTPUT_PENDING
        ```
      </Step>
    </Steps>
  </Tab>
</Tabs>

Then wait until every server is ready:

```bash
kubectl --context YOUR_KUBE_CONTEXT -n kubemq wait --for=condition=Ready kubemqclusters.next.kubemq.io/messaging --timeout=10m
```

Replace: `YOUR_KUBE_CONTEXT` — your cluster's kubectl context; `kubectl config get-contexts` lists them.

You should see:

```text title="Output"
HARNESS_OUTPUT_PENDING
```

Check the license:

```bash
kmq license --kube-context YOUR_KUBE_CONTEXT
```

You should see:

```text title="Output"
HARNESS_OUTPUT_PENDING
```

Then send a test message as in [Install on Kubernetes](/deploy/install/kubernetes#send-a-test-message).

<Accordions>
  <Accordion title="Pin a version">
    **kmq**



    Open the [Release notes](/release-notes) and copy the release number exactly as shown.

    If kmq is installed, switch it to that release:

    ```bash
    kmq update --version YOUR_VERSION
    ```

    Replace: `YOUR_VERSION` — the release number you copied, with a leading `v`.

    On a machine without kmq, download the installer as [Try KubeMQ](/deploy/quickstart#install-kmq) shows, then run it with that release:

    ```bash
    sh install-kmq.sh --version YOUR_VERSION
    ```

    On Windows, in PowerShell:

    ```powershell
    & .\install-kmq.ps1 -Version YOUR_VERSION
    ```

    That kmq installs its matching server release. A pinned install does not update itself: read the release notes and move to the latest release regularly. `kmq update` with no `--version` returns kmq to the latest release.

    **Docker**



    Open the [Release notes](/release-notes) and copy the release number exactly as shown. Wherever a command names `kubemq-next:latest`, write `kubemq-next:YOUR_VERSION` instead, and remove `--pull always` from the `docker run` or `podman run` command.

    Replace: `YOUR_VERSION` — the release number you copied, with a leading `v`.



    To pin by digest, write `kubemq-next@YOUR_DIGEST` instead, with the server image digest the release notes list.

    Replace: `YOUR_DIGEST` — the digest, starting `sha256:`.

    Pinned installs do not update themselves. Check the release notes and move to the latest release regularly.

    **Helm**



    Open the [Release notes](/release-notes) and copy the release number exactly as shown. Add `--version YOUR_VERSION` to every `helm upgrade --install` command and, when you upgrade, to `helm show crds`. Use the same value for the operator release and the cluster release, so the custom resource definitions match the pinned operator. `helm search repo kubemq-next/kubemq-next --versions` lists every published chart version.

    Replace: `YOUR_VERSION` — the release number you copied, with no leading `v`.

    Pinned installs do not update themselves. Check the release notes and move to the latest release regularly.
  </Accordion>
</Accordions>

## Roll back [#roll-back]

A store written by a newer release may not be readable by an older one. Roll back only when the release notes say the upgrade is reversible: install the previous release as "Pin a version" shows, and on Kubernetes also run `helm rollback` for the operator. Otherwise, restore your backup as in [Back up and restore](/operate/backup-and-restore); for Kubernetes, contact support first.

## Move from the old combined chart release [#combined-release]

Older charts put the operator and the cluster in one Helm release. The current chart refuses a release that enables both: `operator and cluster must use independent releases`. [Contact support](mailto:support@kubemq.io) before upgrading a release that contains both the operator and the cluster.



## If something goes wrong [#if-something-goes-wrong]

* **The servers still run the old release.** Run the wait command again. If they stay old, repeat the Helm steps without `--reuse-values`.
* **A server restarts with a storage error in its log.** Restore your backup and check the release notes.
* **A licensing message in the log.** Look up the anchor it prints in [Troubleshooting](/licensing/troubleshooting).

## Next steps [#next-steps]

<Cards>
  <Card title="Release notes" href="/release-notes" description="What each release changed and what to check before you upgrade." />

  <Card title="Production checklist" href="/deploy/production-checklist" description="What else a cluster you rely on needs." />

  <Card title="Move from legacy KubeMQ" href="/deploy/upgrade/from-legacy" description="Leave the older kubemq image or chart." />
</Cards>


## Container command examples

```sh
docker run -d \
  --pull always \
  --platform linux/amd64 \
  --name kubemq \
  --hostname kubemq \
  -p 127.0.0.1:50000:50000 \
  -p 127.0.0.1:9090:9090 \
  -p 127.0.0.1:8080:8080 \
  -p 127.0.0.1:9092:9092 \
  --env-file kubemq-license.env \
  -e STORE_ENGINE=next \
  -e STORE_NEXT_ACK_POLICY=strict \
  -e STORE_STORE_PATH=/kubemq/store \
  -e API_BIND_ADDRESS=0.0.0.0 \
  -v kubemq-data:/kubemq/store \
  europe-docker.pkg.dev/kubemq/images/kubemq-next:latest
```