> For the complete documentation index, see [llms.txt](https://documentation.immuta.com/latest/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://documentation.immuta.com/latest/configuration/self-managed-deployment/upgrade-immuta.md).

# Upgrade to 2026.2

## Requirement

* You must be on the most [recent LTS release](/latest/releases/release-lifecycle.md#release-lifecycle-schedule) or newer to upgrade directly to this version of Immuta.
* Back up the audit database.

## Changes introduced in 2026.2

The following changes are new to 2026.2 and will require additional action before you upgrade. See details about each change in the linked sections below:

* [**Helm chart changes**](#helm-chart-changes)
  * [**Ingress migration**](#ingress-migration): The ingress configuration values in the Helm chart have moved.
  * [**Onboarding service**](#onboarding-service): The Immuta deployment now has an onboarding service, which must be represented in the Helm chart.
  * [**Tenant ID**](#tenant-id): A global tenant ID must now be manually set in the Helm chart as a UUID.
  * [**OpenSearch index**](#opensearch-index-names): Your OpenSearch cluster index names must now be manually set in the Helm chart.
* [**Guardrail subscription policies**](#guardrail-subscription-policies): Global policies now have the option to grant or guardrail users' access. The migration to these two options is automated, but you should check your subscription policies before the upgrade to ensure you understand the impact.

## Upgrade Immuta

1. [**Add the Onboarding service**](#onboarding-service) to your `immuta-values.yaml` file. This value is required and must be set to use the same database as `secure.postgresql.database`.

   <pre class="language-yaml" data-expandable="true"><code class="lang-yaml">secure:
     postgresql:
       database: immuta
       ssl: true

   onboarding:
     postgresql:
       database: immuta
   </code></pre>

   <div data-gb-custom-block data-tag="hint" data-style="warning" class="hint hint-warning"><p><strong>If you store database credentials in a Kubernetes secret</strong> (<code>secure.existingSecret.name</code>), you must also add an <code>ONBOARDING_DATABASE_URL</code> key to that secret and set <code>onboarding.existingSecret</code>. Otherwise, the upgrade fails with <code>onboarding.postgresql.password is required</code>. See the <a href="#existing-kubernetes-secrets">Existing Kubernetes secrets section</a> for more details.</p></div>
2. [Set the **new tenant ID**](#tenant-id) as a UUID under `global.tenantId` in `immuta-values.yaml`:

   ```yaml
   global:
     tenantId: <NEW_UUID>
   ```
3. [Set your **OpenSearch cluster index names**](#opensearch-index-names) under `audit.config.searchIndexName` and `audit.config.searchIndexAliasName` in `immuta-values.yaml`:

   ```yaml
   audit:
     config:
       searchIndexName: <INDEX-NAME>
       searchIndexAliasName: <INDEX-ALIAS>
   ```
4. [Migrate **`secure.ingress` Helm values** **to `gateway.ingress`**](#ingress-migration) , [check the impact of the **guardrail policy upgrade**](#guardrail-subscription-policies), and [upgrade Immuta](#user-content-fn-1)[^1] using one of the methods below.

<details>

<summary><strong>Method A: Zero load-balancer impact (recommended)</strong></summary>

{% hint style="danger" %}
Upgrading with a migrated values file WITHOUT the keep annotation deletes the ingress resource and the load balancer, and there is no self-service recovery without DNS control.
{% endhint %}

Your load balancer is bound to your ingress resource. This migration method keeps that resource across the upgrade and only changes what it points at.

{% hint style="warning" %}
The `keep` annotation only works through values plus a Helm upgrade. Annotating the live object with `kubectl` does not work.
{% endhint %}

1. Edit the `immuta-values.yaml` file and mark this ingress to be kept by adding `helm.sh/resource-policy: "keep"` to `secure.ingress.annotations`. For example,

   <pre class="language-yaml" data-expandable="true"><code class="lang-yaml">secure:
     ingress:
       enabled: true
       hostname: &#x3C;immuta-fqdn>
       ingressClassName: nginx
       annotations:
         nginx.ingress.kubernetes.io/proxy-body-size: '64m'
         helm.sh/resource-policy: "keep"
   </code></pre>
2. Run a same-version upgrade. Replace the content in angle brackets with your release name and the version of Immuta you're currently on (not the one you will upgrade to), respectively.

   <pre data-expandable="true"><code>helm upgrade &#x3C;release-name> oci://ocir.immuta.com/stable/immuta-enterprise --values immuta-values.yaml --version &#x3C;your-current-immuta-version>
   </code></pre>
3. Edit your `immuta-values.yaml` file and remove `secure.ingress` (or set `secure.ingress: null`) and set `gateway.ingress.enabled: false`.

   <pre class="language-yaml" data-expandable="true"><code class="lang-yaml">gateway:
     ingress:
       enabled: false
   </code></pre>
4. Run an impact assessment for the [guardrail policy migration](#guardrail-subscription-policies) to get a list of data sources that fall into one of the two outlined [policy migration scenarios](#policy-migration-scenarios). The access criteria for any data sources listed under **Scenario 2 (ACCESS CHANGES)** in the report has become less restrictive, potentially leading to more users getting subscribed to those data sources after the upgrade. Determine whether to accept those changes or adjust those policies to be **always required** before upgrading Immuta. For guidance, see the [second policy migration scenario](#migration-scenario-2-always-required-and-shared-responsibility-policies-applied-to-a-data-source).\
   \
   The sequence of commands below does not upgrade Immuta or run the full Helm chart; it only runs the temporary Kubernetes Job that generates a list of data sources affected by the guardrail policy migration and then deletes the Job.

   <pre data-expandable="true"><code>helm template immuta oci://ocir.immuta.com/stable/immuta-enterprise --version 2026.2.2 -n &#x3C;ns> -f immuta-values.yaml \
     --show-only charts/secure/templates/guardrail-report-job.yaml | kubectl -n &#x3C;ns> apply -f -
   kubectl -n &#x3C;ns> wait --for=condition=complete job/immuta-secure-guardrail-report --timeout=5m
   kubectl -n &#x3C;ns> logs job/immuta-secure-guardrail-report
   kubectl -n &#x3C;ns> delete job immuta-secure-guardrail-report
   </code></pre>
5. Upgrade to 2026.2. The kept ingress will be skipped, not deleted. During the migration, audit history queries are slower and audit writes pause for a few minutes. Do not interrupt the command, and do not run it a second time while the first is still running.

   1. Replace the content in angle brackets with your release name.
   2. Set a Helm timeout. The upgrade rebuilds indexes on the `auditrecord` table, and on a large table this takes longer than Helm’s default 5 minutes. If this default is not adjusted, when Helm times out it will mark the release as failed while the migration keeps running. [Budget about 30 minutes for every 100 million rows in `bometadata.auditrecord` and pass it as `--timeout`.](#user-content-fn-2)[^2]

   <pre data-expandable="true"><code>helm upgrade &#x3C;release-name> oci://ocir.immuta.com/stable/immuta-enterprise --values immuta-values.yaml --version 2026.2.2 --timeout 3h
   </code></pre>
6. Verify the pods are running and jobs are complete.

   <pre data-expandable="true"><code>kubectl -n &#x3C;ns> get pods                       # all Running / Completed
   kubectl -n &#x3C;ns> get jobs                       # all Complete, incl. onboarding-db-migrator and temporal-cleanup
   kubectl -n &#x3C;ns> get ingress                    # &#x3C;release>-secure still present
   kubectl -n &#x3C;ns> get deploy &#x3C;release>-gateway   # 1/1 ready
   </code></pre>
7. Cut over the kept ingress backend to `<release>-gateway`, port `8000`. Expect up to about 10 seconds of HTTP 503 at the cutover. The kept ingress will be unmanaged by Helm.

   <pre data-expandable="true"><code>kubectl -n &#x3C;ns> patch ingress &#x3C;release>-secure --type=json -p '[
     {"op":"replace","path":"/spec/rules/0/http/paths/0/backend/service/name","value":"&#x3C;release>-gateway"},
     {"op":"replace","path":"/spec/rules/0/http/paths/0/backend/service/port","value":{"number":8000}}
   ]'
   </code></pre>
8. Confirm that traffic transits the gateway.

   <pre data-expandable="true"><code>kubectl -n &#x3C;ns> logs deploy/&#x3C;release>-gateway --since=1m | grep -c DownstreamStatus
   </code></pre>

The ingress is now **unmanaged by Helm** and will keep working indefinitely; future `helm upgrade` runs will not affect it. If you later want a chart-managed ingress, complete the steps outlined in [Method B](#method-b-chart-managed-ingress-requires-dns-control) at any time.

</details>

<details>

<summary><strong>Method B: Chart-managed ingress (requires DNS control)</strong></summary>

1. Edit the `immuta-values.yaml` file and mark this ingress to be kept by adding `helm.sh/resource-policy: "keep"` to `secure.ingress.annotations`. For example,

   <pre class="language-yaml" data-expandable="true"><code class="lang-yaml">secure:
     ingress:
       enabled: true
       hostname: &#x3C;immuta-fqdn>
       ingressClassName: nginx
       annotations:
         nginx.ingress.kubernetes.io/proxy-body-size: '64m'
         helm.sh/resource-policy: "keep"
   </code></pre>
2. Run a same-version upgrade. Replace the content in angle brackets with your release name and the version of Immuta you're currently on (not the one you will upgrade to), respectively.

   <pre data-expandable="true"><code>helm upgrade &#x3C;release-name> oci://ocir.immuta.com/stable/immuta-enterprise --values immuta-values.yaml --version &#x3C;your-current-immuta-version>
   </code></pre>
3. Edit the `immuta-values.yaml` file and move the `secure.ingress` values to `gateway.ingress`. See the [Ingress configuration guide](/latest/configuration/self-managed-deployment/configure/ingress-configuration.md) for instructions specific to your ingress controller. For example,

   <pre class="language-yaml" data-expandable="true"><code class="lang-yaml">gateway:
     ingress:
       enabled: true
       hostname: immuta.example.com
       ingressClassName: alb
       annotations: { ...your ALB annotations, cert ARN, etc... }
   </code></pre>
4. Run an impact assessment for the [guardrail policy migration](#guardrail-subscription-policies) to get a list of data sources that fall into one of the two outlined [policy migration scenarios](#policy-migration-scenarios). The access criteria for any data sources listed under **Scenario 2 (ACCESS CHANGES)** in the report has become less restrictive, potentially leading to more users getting subscribed to those data sources after the upgrade. Determine whether to accept those changes or adjust those policies to be **always required** before upgrading Immuta. For guidance, see the [second policy migration scenario](#migration-scenario-2-always-required-and-shared-responsibility-policies-applied-to-a-data-source).\
   \
   The sequence of commands below does not upgrade Immuta or run the full Helm chart; it only runs the temporary Kubernetes Job that generates a list of data sources affected by the guardrail policy migration and then deletes the Job.

   <pre data-expandable="true"><code>helm template immuta oci://ocir.immuta.com/stable/immuta-enterprise --version 2026.2.2 -n &#x3C;ns> -f immuta-values.yaml \
     --show-only charts/secure/templates/guardrail-report-job.yaml | kubectl -n &#x3C;ns> apply -f -
   kubectl -n &#x3C;ns> wait --for=condition=complete job/immuta-secure-guardrail-report --timeout=5m
   kubectl -n &#x3C;ns> logs job/immuta-secure-guardrail-report
   kubectl -n &#x3C;ns> delete job immuta-secure-guardrail-report
   </code></pre>
5. Upgrade to 2026.2. A **second** load balancer is provisioned for the new `<release>-gateway` ingress while the old one keeps serving. During the migration, audit history queries are slower and audit writes pause for a few minutes. Do not interrupt the command, and do not run it a second time while the first is still running.

   1. Replace the content in angle brackets with your release name.
   2. Set a Helm timeout. The upgrade rebuilds indexes on the `auditrecord` table, and on a large table this takes longer than Helm’s default 5 minutes. If this default is not adjusted, when Helm times out it will mark the release as failed while the migration keeps running. [Budget about 30 minutes for every 100 million rows in `bometadata.auditrecord` and pass it as `--timeout`.](#user-content-fn-2)[^2]

   <pre data-expandable="true"><code>helm upgrade &#x3C;release-name> oci://ocir.immuta.com/stable/immuta-enterprise --values immuta-values.yaml --version 2026.2.2 --timeout 3h
   </code></pre>
6. Validate the new load balancer directly by its DNS name, and then flip your DNS record (lower TTL beforehand). Both load balancers serve during the transition; rollback is a DNS flip.
7. Delete the kept legacy ingress.

{% hint style="warning" %}
If external-dns manages records by ingress hostname, two ingresses claiming the same host will fight. Use a temporary hostname for validation or an external-dns exclusion annotation until the flip.
{% endhint %}

</details>

<details>

<summary><strong>Method C: Not using the Helm chart's ingress</strong></summary>

OpenShift routes and external load balancers targeting the `<release>-secure` service keep working.

1. Re-point the backend to `<release>-gateway:8000`, as the gateway strips the `immuta-service-id` header from external requests and is the trust boundary for machine-to-machine auth.
2. Run an impact assessment for the [guardrail policy migration](#guardrail-subscription-policies) to get a list of data sources that fall into one of the two outlined [policy migration scenarios](#policy-migration-scenarios). The access criteria for any data sources listed under **Scenario 2 (ACCESS CHANGES)** in the report has become less restrictive, potentially leading to more users getting subscribed to those data sources after the upgrade. Determine whether to accept those changes or adjust those policies to be **always required** before upgrading Immuta. For guidance, see the [second policy migration scenario](#migration-scenario-2-always-required-and-shared-responsibility-policies-applied-to-a-data-source).\
   \
   The sequence of commands below does not upgrade Immuta or run the full Helm chart; it only runs the temporary Kubernetes Job that generates a list of data sources affected by the guardrail policy migration and then deletes the Job.

   <pre data-expandable="true"><code>helm template immuta oci://ocir.immuta.com/stable/immuta-enterprise --version 2026.2.2 -n &#x3C;ns> -f immuta-values.yaml \
     --show-only charts/secure/templates/guardrail-report-job.yaml | kubectl -n &#x3C;ns> apply -f -
   kubectl -n &#x3C;ns> wait --for=condition=complete job/immuta-secure-guardrail-report --timeout=5m
   kubectl -n &#x3C;ns> logs job/immuta-secure-guardrail-report
   kubectl -n &#x3C;ns> delete job immuta-secure-guardrail-report
   </code></pre>
3. Upgrade Immuta to the latest release. During the migration, audit history queries are slower and audit writes pause for a few minutes. Do not interrupt the command, and do not run it a second time while the first is still running.

   1. Replace the content in angle brackets with your release name.
   2. Set a Helm timeout. The upgrade rebuilds indexes on the `auditrecord` table, and on a large table this takes longer than Helm’s default 5 minutes. If this default is not adjusted, when Helm times out it will mark the release as failed while the migration keeps running. [Budget about 30 minutes for every 100 million rows in `bometadata.auditrecord` and pass it as `--timeout`.](#user-content-fn-2)[^2]

   ```sh
   helm upgrade <release-name> oci://ocir.immuta.com/stable/immuta-enterprise --values immuta-values.yaml --version 2026.2.2 --timeout 3h
   ```

</details>

If you encounter an upgrade failure, see the [Troubleshooting page](/latest/configuration/self-managed-deployment/troubleshooting.md#upgrade-failure) for a list of error messages and remediation steps.

## Changes introduced in 2026.2 that require action before upgrading

This section describes changes that require action before you upgrade Immuta. For a full list of new features and behavior changes, see the [2026.2 release notes](/latest/releases/releases/index.md).

### Helm chart changes

#### Ingress migration

{% hint style="danger" %}
Upgrading with a migrated values file WITHOUT the keep annotation deletes the ingress resource and the load balancer, and there is no self-service recovery without DNS control. See the [Method A migration instructions](#method-a-zero-load-balancer-impact-recommended) for guidance.
{% endhint %}

The ingress configuration values that were previously in `secure.ingress` in the `immuta-values.yaml` file have moved to `gateway.ingress`.

The snippets below show a sample comparison of the 2026.1 ingress configuration and the 2026.2 ingress configuration.

{% columns %}
{% column %}
**2026.1 Helm values**

{% code expandable="true" %}

```yaml
secure:
  postgresql:
    database: immuta
    ssl: true
  ingress:
    enabled: true
    hostname: <immuta-fqdn>
    annotations:
      # Determines which type of load balancer is provisioned
      #   gce-internal
      #   gce
      kubernetes.io/ingress.class: gce
      # Listen on both 80 and 443
      kubernetes.io/ingress.allow-http: 'true'
      # Redirect traffic from 80 to 443
      cloud.google.com/frontend-config: immuta
```

{% endcode %}
{% endcolumn %}

{% column %}
**2026.2 Helm values**

{% code expandable="true" %}

```yaml
secure:
  postgresql:
    database: immuta
    ssl: true
gateway:
  ingress:
    enabled: true
    hostname: <immuta-fqdn>
    annotations:
      # Determines which type of load balancer is provisioned
      #   gce-internal
      #   gce
      kubernetes.io/ingress.class: gce
      # Listen on both 80 and 443
      kubernetes.io/ingress.allow-http: 'true'
      # Redirect traffic from 80 to 443
      cloud.google.com/frontend-config: immuta
```

{% endcode %}
{% endcolumn %}
{% endcolumns %}

The Helm chart will not upgrade if `secure.ingress` is still present; however, removing that content without following one of the migration methods linked below will delete your ingress resource and load balancer irrevocably. In order to upgrade Immuta, use one of the following methods detailed in the upgrade Immuta section to migrate ingress:

* [**Method A: Zero load-balancer impact (recommended)**](#method-a-zero-load-balancer-impact-recommended)**:** This migration method keeps the ingress resource across the upgrade and only changes what it points at.
* [**Method B: Chart-managed ingress (requires DNS control)**](#method-b-chart-managed-ingress-requires-dns-control)**:** You can use this method if your team controls DNS and load-balancer provisioning directly. This method gets you a fully chart-managed ingress at the cost of one planned DNS cutover.
* [**Method C: Not using the Helm chart's ingress**](#method-c-not-using-the-helm-charts-ingress)**:** Use this method if you do not use the Helm chart's ingress and instead use OpenShift or a corporate load balancer pointed at the secure service. This method has minimal impact, but includes one recommended follow-up.

#### Onboarding service

2026.2 introduces the Onboarding service. The Helm value `onboarding.postgresql.database` is required and must be set to use the same database as `secure.postgresql.database`, not a new database. The upgrade will fail without it. See the [upgrade Immuta section](#upgrade-immuta) for instructions.

{% columns %}
{% column %}
**2026.1 Helm values**

{% code expandable="true" %}

```yaml
secure:
  postgresql:
    database: immuta
    ssl: true
```

{% endcode %}
{% endcolumn %}

{% column %}
**2026.2 Helm values**

{% code expandable="true" %}

```yaml
secure:
  postgresql:
    database: immuta
    ssl: true

onboarding:
  postgresql:
    database: immuta
```

{% endcode %}
{% endcolumn %}
{% endcolumns %}

**Existing Kubernetes secrets**

If your values file references database credentials in an existing Kubernetes secret with `secure.existingSecret.name`, the chart cannot build the Onboarding database connection string for you. Complete these steps before you upgrade:

1. Add an `ONBOARDING_DATABASE_URL` key to the secret, using the process you normally use to manage it. Use the same user, host, and database that Secure uses, and URL-encode any special characters in the password (for example, `@` becomes `%40` and `%` becomes `%25`).

   ```
   postgres://<user>:<url-encoded-password>@<postgres-fqdn>:5432/<database>?schema=onboarding
   ```
2. Set `onboarding.existingSecret` to the secret's name. This value takes the name as a string, unlike `secure.existingSecret.name`.

   ```yaml
   secure:
     existingSecret:
       name: immuta-secret

   onboarding:
     existingSecret: immuta-secret
     postgresql:
       database: immuta
   ```

{% hint style="info" %}
Secure's web and background worker pods also read `ONBOARDING_DATABASE_URL` from `secure.existingSecret` in 2026.2. If the key is missing, those pods fail to start with `couldn't find key ONBOARDING_DATABASE_URL in Secret`, so add the key even if you configure Onboarding another way.
{% endhint %}

The Onboarding migrator creates an `onboarding` schema inside the existing database, so the database user must be able to create a schema there.

#### Tenant ID

This section applies to self-managed deployments with `audit-service` enabled.

As part of the upgrade to 2026.2, update the audit tenant ID in the Helm values and the configuration used to send events to `audit-service`. The tenant ID must be a UUID. It will identify your audit history and must stay the same for future upgrades.

#### OpenSearch index names

This section applies to self-managed deployments with `audit-service` enabled.

**Before you begin**

Confirm that the OpenSearch user has the `indices:data/write/update/byquery` permission for the audit index. This is a new [permission requirement](/latest/configuration/self-managed-deployment/deployment-requirements.md#opensearch-user) for 2026.2.

**Find your OpenSearch index names**

Run the following report on your current deployment, before upgrading:

```sh
helm template <release-name> oci://ocir.immuta.com/stable/immuta-enterprise --version 2026.2.2 -n <namespace> -f immuta-values.yaml \
  --show-only charts/audit/templates/search-index-report-job.yaml | kubectl -n <namespace> apply -f -
kubectl -n <namespace> wait --for=condition=complete job/<release-name>-audit-search-index-report --timeout=5m
kubectl -n <namespace> logs job/<release-name>-audit-search-index-report
kubectl -n <namespace> delete job <release-name>-audit-search-index-report
```

This report reads your search cluster through the audit service’s own credentials, changes nothing, and prints the values to set when upgrading.

**Output example**:

```yaml
[SEARCH-INDEX-REPORT] Existing audit index for tenant <id>: <index> (alias <alias>). Add to your values file:
audit:
  config:
    searchIndexName: <index>
    searchIndexAliasName: <alias>
```

Use those names in the `immuta-values.yaml` file when [upgrading Immuta](#upgrade-immuta).

### Guardrail subscription policies

[Guardrail subscription policies](/latest/governance/author-policies-for-data-access-control/authoring-policies-in-secure/section-contents/reference-guides/subscription-policies.md#guardrail-subscription-policy) prevent users from gaining access to data unless they meet specific conditions. For some customers, moving to this new feature entails an automated migration of existing subscription policy logic. Subscription policies that use the **shared responsibility** option become grant policies. Subscription policies that use the **always required** option also become grant policies, and the migration creates a matching guardrail policy only when the always required policy is merged with another subscription policy on at least one data source. See the [policy migration scenarios](#policy-migration-scenarios) for details.

| Before upgrade                                                            | After upgrade                       |
| ------------------------------------------------------------------------- | ----------------------------------- |
| Always required, merged with another subscription policy on a data source | Grant policy and a guardrail policy |
| Always required, not merged with another subscription policy              | Grant policy (no guardrail policy)  |
| Shared responsibility                                                     | Grant policy                        |

When migrating always required to guardrail subscription policies, there is one key difference in behavior: An always required policy would still subscribe users, but a guardrail policy will not; instead, guardrail policies ensure that users only get access to data if they are part of the eligible set of users, but no user will be actually subscribed unless there is also at least one grant policy targeting the data source. The table below illustrates this behavior with a policy example.

<table><thead><tr><th width="118.51953125"></th><th>Before upgrade (always required policy)</th><th>After upgrade (guardrail policy)</th></tr></thead><tbody><tr><td><strong>Policy</strong></td><td>Subscribe users when user is a member of group <code>Finance</code> on all data sources tagged sales.</td><td>Prevent users from gaining access unless user is a member of group <code>Finance</code> on all data sources tagged sales.</td></tr><tr><td><strong>Result</strong></td><td>Everyone from <code>Finance</code> gets subscribed</td><td>Nobody gets subscribed, but if there is any grant policy trying to give access to someone that is not in <code>Finance</code>, those users will be blocked</td></tr></tbody></table>

Before you upgrade Immuta to 2026.2, [run an impact assessment by following the steps in the upgrade Immuta section](#upgrade-immuta) to identify what data sources have subscription policies applied to them that will be affected by the upgrade.

#### Policy migration scenarios

Click below to expand explanations of the migration scenarios so that you understand policies that will be created in your tenant and how they will affect users' access.

<details>

<summary>Migration Scenario 1: Multiple always required policies applied to a data source</summary>

This scenario applies to any data source that has multiple always required policies applied to them. The table below outlines the migration logic.

|                         | Before upgrade                                                                                                                                                                                                                                                                                                                 | After upgrade                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                   |
| ----------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Policies**            | <ul><li>Policy 1 (always required): Subscribe users when user is a member of group <code>Finance</code></li><li>Policy 2 (always required): Subscribe users when user is a member of group <code>Marketing</code></li><li>Policy 3 (always required): Subscribe users when user is a member of group <code>HR</code></li></ul> | <ul><li>Policy 1 (grant policy): Subscribe users when user is a member of group <code>Finance</code></li><li>Policy 1.1 (guardrail policy): Prevent users from gaining access unless user is a member of group <code>Finance</code></li><li>Policy 2 (grant policy): Subscribe users when user is a member of group <code>Marketing</code></li><li>Policy 2.1 (guardrail policy): Prevent users from gaining access unless user is a member of group <code>Marketing</code></li><li>Policy 3 (grant policy): Subscribe users when user is a member of group <code>HR</code></li><li>Policy 3.1 (guardrail policy): Prevent users from gaining access unless user is a member of group <code>HR</code></li></ul> |
| **Merged policy logic** | <p>Users will be subscribed to the data source</p><p>when they are member of group <code>Finance</code> AND <code>Marketing</code> AND <code>HR</code>.</p><p><br></p>                                                                                                                                                         | <p>Users will be subscribed to the data source when they are (a member of group <code>Finance</code> OR <code>Marketing</code> OR <code>HR</code>)</p><p>AND</p><p>(a member of group <code>Finance</code> AND <code>Marketing</code> AND <code>HR</code>).</p>                                                                                                                                                                                                                                                                                                                                                                                                                                                 |

In this scenario, the final access criteria **remains the same**: A user will not get subscribed to this data source unless they are a member of all the three required groups. However, in order for nobody to lose access, the migration turns each always required policy into two policies — one grant policy and one corresponding guardrail policy — ultimately resulting in a higher number of policies than before the upgrade.

</details>

<details>

<summary>Migration Scenario 2: Always required and shared responsibility policies applied to a data source</summary>

This scenario applies to any data source that has exactly one shared responsibility and one or more always required policies applied. The table below outlines the migration logic.

|                         | Before upgrade                                                                                                                                                                                                                      | After upgrade                                                                                                                                                                                                                                                                                                                                                |
| ----------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Policies**            | <ul><li>Policy 1 (shared responsibility): Subscribe users when user is a member of group <code>Sales</code></li><li>Policy 2 (always required): Subscribe users when user is a member of group <code>Manufacturing</code></li></ul> | <ul><li>Policy 1 (grant policy): Subscribe users when user is a member of group <code>Sales</code></li><li>Policy 2 (grant policy): Subscribe users when user is a member of group <code>Manufacturing</code></li><li>Policy 2.1 (guardrail policy): Prevent users from gaining access unless user is a member of group <code>Manufacturing</code></li></ul> |
| **Merged policy logic** | <p>Users will be subscribed they are a member of group <code>Sales</code> AND <code>Manufacturing</code>.</p><p>In this example, the policies are combined with AND because there is an always required policy in play.</p>         | Users will be subscribed to this data source when they are (a member of group `Sales` OR `Manufacturing`) AND (a member of group `Manufacturing`).                                                                                                                                                                                                           |

In this scenario, the final access criteria **does not remain the same**: A user will now get subscribed to this data source as long as they are a member of group `Manufacturing`; being a member of group `Sales` is no longer a hard requirement. The access criteria for this data source has become less restrictive, potentially leading to more users getting subscribed to this data source after the upgrade.

Given that this scenario leads to a change in access, you have the following options:

1. Do nothing and accept the change in behavior for affected data sources
2. Change the shared responsibility policy into an always required policy, which will turn the data source into a [scenario 1 migration case](#migration-scenario-1-multiple-always-required-policies-applied-to-a-data-source) instead.

Contact your Immuta representative if you would like receive guidance in making the right decision for your case.

</details>

<details>

<summary>Migration Scenario 3: Always required policy not merged with another subscription policy</summary>

This scenario applies to any always required policy that is not merged with another subscription policy on a data source. This includes always required policies that apply to no data sources and always required policies that are the only subscription policy on the data sources they apply to. The table below outlines the migration logic.

|                         | Before upgrade                                                                       | After upgrade                                                                      |
| ----------------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------- |
| **Policies**            | Policy 1 (always required): Subscribe users when user is a member of group `Finance` | Policy 1 (grant policy): Subscribe users when user is a member of group `Finance`  |
| **Merged policy logic** | Users are subscribed to the data source when they are a member of group `Finance`.   | Users are subscribed to the data source when they are a member of group `Finance`. |

In this scenario, the final access criteria **remains the same**. The always required option only affects how a policy combines with other subscription policies on a data source, so the migration converts the policy to a grant policy and does not create a guardrail policy.

After the upgrade, if another grant policy applies to the same data source, the two grant policies combine with OR. To keep a condition mandatory on a data source, create a [guardrail policy](/latest/governance/author-policies-for-data-access-control/authoring-policies-in-secure/section-contents/reference-guides/subscription-policies.md#guardrail-subscription-policy) with that condition.

</details>

#### API changes

Once the guardrail feature is enabled, the Immuta system will automatically handle the `shareResponsibility` parameter in [subscription policy payloads](/latest/developer-guides/api-intro/immuta-v1-api/manage-data-access/policy.md#request-example).

The system enforces the following rules:

* `"subscriptionType": "policy"` always equals `"shareResponsibility": true`
* `"subscriptionType": "guardrail"` always equals `"shareResponsibility": false`

This ensures backwards compatibility so that you can continue sending your existing policy payloads. However, user-provided values for the `shareResponsibility` parameter will be ignored, as they are now implicitly defined as part of the `subscriptionType`. See the below table for a summary of the behavior change.

| Policy payload                                                                                   | System behavior                                                                                  |
| ------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------ |
| <p><code>"subscriptionType": "policy"</code><br><code>"shareResponsibility": true</code></p>     | <p><code>"subscriptionType": "policy"</code><br><code>"shareResponsibility": true</code></p>     |
| <p><code>"subscriptionType": "policy"</code><br><code>"shareResponsibility": false</code></p>    | <p><code>"subscriptionType": "policy"</code><br><code>"shareResponsibility": true</code></p>     |
| <p><code>"subscriptionType": "guardrail"</code><br><code>"shareResponsibility": true</code></p>  | <p><code>"subscriptionType": "guardrail"</code><br><code>"shareResponsibility": false</code></p> |
| <p><code>"subscriptionType": "guardrail"</code><br><code>"shareResponsibility": false</code></p> | <p><code>"subscriptionType": "guardrail"</code><br><code>"shareResponsibility": false</code></p> |

### Connections

{% hint style="info" %}
With connections enabled, some API endpoints will be blocked. Please see the [API changes page](/latest/configuration/self-managed-deployment/upgrade-immuta/api-changes.md) for details about API endpoints that will become unavaible for Snowflake, Databricks Unity Catalog, and Starburst (Trino) integrations after you upgrade to 2026.2.
{% endhint %}

After you complete the upgrade to 2026.2, connections will be enabled by default and you will see a banner to upgrade your integrations to connections. [Follow the steps in the UI to complete the upgrade](/latest/configuration/integrations/registering-metadata/connections/how-to-guides/use-the-connection-upgrade-manager.md).

[^1]: Upgrades from 2025.1 can leave behind an orphaned Temporal schedule that floods the Temporal logs with `pq: syntax error in tsvector` errors. A post-upgrade job removes the orphaned schedule automatically during the upgrade; no action is required.

[^2]: If you do not know the row count, ask your database administrator to run `SELECT count(*) FROM bometadata.auditrecord`.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation by asking a question.

Perform an HTTP GET request on the following URL with the `ask` and `goal` query parameters:

```
GET https://documentation.immuta.com/latest/configuration/self-managed-deployment/upgrade-immuta.md?ask=<question>&goal=<user_goal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is what the user is ultimately trying to achieve, the reason they need the answer. Sharing it helps GitBook give you a better, more relevant answer. A goal is most helpful when it describes the outcome the user wants rather than restating the question. For example, with `ask=how do I create an API token`, a goal like `automate deployments from our CI pipeline` lets GitBook tailor the answer to that use case.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
