Skip to main content
Available starting with FlowX.AI 5.9.6. The flowx-ai chart deploys the core and AI services as one Helm release.
In FlowX.AI 5.9.6 you can still install the core services with one Helm chart per service. Starting with the next LTS release family, the flowx-ai chart is the only supported way to deploy the platform.

Overview

The migration replaces your platform workloads once. Your databases, stored files, and indexed qdrant collections are kept.

What stays the same?

  • Your data. Databases, files in the object store, and qdrant collections carry over.
  • Datastores. The chart does not install, change, or delete PostgreSQL, MongoDB, Redis, Elasticsearch, Kafka, or your object store.
  • Persistent volumes. The qdrant volume claims keep their names and are reattached. See PVC behavior.
  • Resource names. Deployments, Services, and Ingresses keep their per-service names, except for the objects listed in Other behavior changes.

What changes?

The workload labels change, and they are part of spec.selector. Kubernetes does not allow the selector of an existing Deployment or StatefulSet to change, so helm upgrade cannot move a workload from the old charts to the new one. Every Deployment must be deleted and recreated. The qdrant StatefulSet must be recreated too, unless the flowx-ai release keeps the release name of your ai-platform release: qdrant keeps its app and app.kubernetes.io/name labels, so its selector changes only through app.kubernetes.io/instance.
The services are unavailable from the time you delete the old workloads until the new pods are ready. Plan a maintenance window.
The flowx-ai chart deploys the platform version it was released with, so the migration also upgrades every service to that version. Before the window, read the upgrade notes of every release between your current version and the chart’s version, including the 5.9.6 upgrade notes.

Before you begin

Support for the previous charts

  • ai-platform umbrella chart: retired. From FlowX.AI 5.9.6, the AI services ship in the flowx-ai chart.
  • Per-service charts: move to the flowx-ai chart so that later upgrades are a single helm upgrade of one release.

Prerequisites

  • Helm 3 and kubectl, with access to the namespace that runs FlowX.AI
  • jq and yq v4 (the mikefarah Go version), for the commands in this guide
  • Pull access to the flowx-ai chart in the chart registry FlowX provides for your installation, at the chart version for your target release. The chart version is the platform release, for example 5.9.6.
  • For the default Gateway API mode: the Gateway API CRDs (gateway.networking.k8s.io/v1) in the cluster, a Gateway controller, and a Gateway named default-gateway with an https listener in the FlowX.AI namespace. The chart attaches its HTTPRoutes to that Gateway but does not create it. To use an existing Gateway, set its name and namespace in gatewayName and gatewayNamespace under global.flowx.gateway.public, global.flowx.gateway.admin, and global.flowx.gateway.adminInstances. Without the CRDs the chart does not render and fails with Gateway API HTTPRoute CRD (gateway.networking.k8s.io/v1) not found. To use Kubernetes Ingress instead, see Check the global settings.
  • Image pull secrets for every service in the namespace, AI services included. The chart applies imagePullSecrets to all pods.
  • The flowx-events-gateway-sa client and its secret in your identity provider realm. events-gateway authenticates with it in the flowx-ai chart.
  • If SpiceDB already runs in your environment: spicedb-operator.enabled: false and spicedb-cluster.enabled: false in your values. The chart installs both by default.
  • A backup of PostgreSQL, MongoDB, the object store, and the qdrant collections, taken right before the maintenance window. It is your recovery point for a rollback.
  • A maintenance window. Measure the delete-to-ready time in a test environment first.
The commands in this guide read the namespace from NS. Set it once in your shell:

Service groups

Every service in the chart belongs to exactly one group, set in services.<name>.group. A service with no group belongs to base. You turn a whole group on or off under groups. The groups replace the devtime and runtime flags of the ai-platform umbrella chart. The qdrant vector database follows the base group. qdrant.enabled overrides the group when you set it: true deploys qdrant with base off, and false leaves it out with base on.

How do the switches combine?

The chart decides whether a service runs in this order:
  1. services.<name>.enabled, if you set it, wins.
  2. Otherwise, groups.<group>.enabled applies, from your values or from the chart default.
For example, these values turn on the runtime group but leave out speech-to-text:
To run the core platform without any AI services, turn off base, devtime, and runtime. qdrant is left out together with base.
Group defaults can change between chart versions. Set every group explicitly in your values, so your installation behaves the same after any chart upgrade.

How do the umbrella flags map?

If your values still contain a top-level devtime or runtime key, the chart fails to render with the message top-level devtime/runtime flags moved. This is intentional: left in place, those keys would be ignored and only the base group would deploy.

Convert your values

The flowx-ai chart reads one values tree. Most of your settings go under three top-level keys:
  • global: settings shared by every service, such as domain, identity provider, datastore servers, registry, and ingress
  • groups: turns service groups on and off. See Service groups.
  • services.<name>: the settings of one service
The bundled components keep their own top-level keys: qdrant, spicedb-operator, spicedb-cluster, and dataSync. The chart validates the shape of your values. It fails to render if it finds a service key at the top level instead of under services, a top-level image or podLabels key, or a group that the chart does not declare. The per-service charts and the flowx-ai chart use the same values structure for a service, so most keys inside a service keep their names. The work is mostly moving keys and removing duplicates.

From the per-service charts

1

Merge the global blocks

Take the global block of each release’s current values and merge them into one global block. Where two releases set the same key to different values, choose the value that is correct for the whole platform.
2

Move each service's keys under services

Move every other top-level key of a service’s values file under services.<name>. For example, resources in values-application-manager.yaml becomes services.application-manager.resources:
3

Remove image tag overrides

Delete image.tag from each service’s values. The service version moves to services.<name>.version, which the chart pins to the platform release of the chart version. A leftover tag override keeps that service on its old version while the rest of the platform moves.

From the ai-platform umbrella chart

1

Move each service key under services

Move each root-level service key under services. For example, embedder: becomes services.embedder:.
2

Replace the devtime and runtime flags

Use the mapping in How do the umbrella flags map?.
3

Merge the global block

Merge the umbrella’s global block into the shared global block.

Check the global settings

In the old layout, a global value reached only the services of its own release. In the flowx-ai chart, a global value reaches every service. Review these cases before you render:
  • Ingress or Gateway API. The chart routes traffic through Gateway API by default, and global.flowx.ingress.enabled defaults to false. To keep Kubernetes Ingress, set global.flowx.ingress.enabled: true, and set global.flowx.gateway.enabled: false if the cluster has no Gateway API CRDs: turning Ingress on does not turn the Gateway API routes off. A service then gets an Ingress only when its own ingress.enabled is also on. Ingress mode does not strip path prefixes, so services served under a prefix, such as /license, /ai, and /integration, need regex paths with rewrite-target annotations. With Ingress on, five AI services also get an admin Ingress by default: ai-gateway, doc-converter, data-privacy, speech-to-text, and web-crawler. Set ingress.admin.enabled: false on any of them that has none today.
  • global.env, global.podAnnotations, and global.replicaCount. If these came from your core releases, they now also apply to the AI services, for example a Java agent annotation on Python pods. Move them onto the core services that need them.
  • Values set to null to unset a default. The chart validates values against one schema for all services and rejects some of these. Delete them: the result is the same when the chart sets no default for that key.

Choose the release name

The release name becomes part of the name of the CA certificates init container. It is also passed to doc-parser, doc-converter, evals-judge, data-privacy, speech-to-text, and web-crawler in the GRPC_HOST_RESOLVER_HELM_CHART environment variable, for service discovery. Choose a name that no other release in the namespace uses, and keep it for the life of the installation. A name that contains flowx-ai, such as flowx-ai, keeps the generated names short, because the chart does not append -flowx-ai to it.

Render and compare

Render the chart with your new values before the maintenance window, and compare the result with what runs today. Use the chart reference from your FlowX chart registry, and the platform release as the chart version:
Every line in the diff is a behavior change. Resolve each one, or confirm that you expect it, before you continue. Pay particular attention to variables that contain BUCKET, URL, and REALM. The comparison covers inline env values of the first container only. Compare variables that come from valueFrom or envFrom (Secrets and ConfigMaps), and any other containers, separately.

Migrate S3 buckets

The flowx-ai chart sets no bucket names and no bucket prefixes. Carry over the names your services use today, or they start writing to new, empty buckets.
A wrong bucket name does not always fail loudly. A service that is allowed to create buckets creates a missing bucket on first use. New files go to the new bucket, and files stored under the old name are no longer found. Nothing is deleted, but uploaded documents, media library assets, and knowledge base files appear to be missing.

How do bucket names reach a service?

If a value is set, the chart renders it as an environment variable, such as APPLICATION_FILE_STORAGE_S3_BUCKET_PREFIX as rendered by the chart. If it is not set, the chart renders nothing, and the service falls back to the default built into its image. Several of those image defaults are empty. A service that uses a prefix derives its bucket names from it: <prefix>-<file type> for regular uploads, and <prefix> alone for date-partitioned files. Dots become dashes.

Bucket keys and previous defaults

The following table lists every bucket setting and the name a previous chart set when you did not. What this means for your previous charts:
  • From the per-service charts: document-plugin, notification-plugin, cms-core, and the AI services in the table had bucket names set by their chart. The flowx-ai chart does not set them, so set them yourself, even if you never changed them.
  • From the ai-platform umbrella chart: set the AI bucket names explicitly. Most AI image defaults are empty.
  • Services marked None: they used their image default, and keep it if you leave the key unset.

Step 1: Find the names in use

List the bucket and root directory variables that each running service uses:
The filter is broad on purpose, so it can also list unrelated variables, such as a root log level. A service that is missing from the output uses its image default. In your object store, confirm which buckets hold the data, for example with the MinIO console, mc ls, or aws s3 ls.

Step 2: Set the names in your values

Set every name from step 1 under the keys in the table:
Leave a key unset only for a service that should keep its image default. If an earlier values file sets a name you want to clear, remove the key from that file. Do not set it to null. Two differences from the per-service charts need attention when you copy values across:
  • Entry name. The per-service core charts named the S3 entry minio. In flowx-ai the entry is main. Set the prefix under component.s3.main and remove the minio entry: if both are present, the chart fails to render with Only one s3 entry may omit an alias.
  • cms-core root directory. The per-service chart also set a rootDirectory for each cms-core bucket. Files are stored under that directory, so carry over rootDirectory together with bucketName.
If you set the document-plugin prefix with the older MINIO_BUCKET_PREFIX environment variable, move it to bucketPrefix. document-plugin reads MINIO_BUCKET_PREFIX only as a fallback, so a prefix that the chart renders takes precedence. Before the maintenance window, check the names in the render:
Every name from step 1 must appear with the same value.

Step 3: Verify the bucket names after the cutover

1

Check the running values

Run the command from step 1 again and check each value.
2

Open files uploaded before the migration

Open a process attachment, a media library asset, a notification template asset, and a knowledge base document.
3

Check the logs

Look for bucket not found errors in the service logs. They point to a name mismatch.
Do not rename buckets or change root directories as part of this migration. The databases reference stored files by bucket and path, so keep every bucket name, prefix, and rootDirectory exactly as it is today.

PVC behavior

qdrant is the only workload in the chart that stores data on a PersistentVolumeClaim (PVC). Its volumes survive the cutover and are reattached to the new StatefulSet, as long as the conditions in this section hold. If the base group is off and qdrant.enabled is not set, or if you set qdrant.enabled: false, the chart deploys no qdrant StatefulSet. Existing qdrant claims then stay in the namespace unused, until you delete them or turn qdrant back on.

Volumes the chart uses

Databases, Kafka, and the object store run in their own releases. The chart does not create, change, or delete their volumes.

Why do the volumes survive?

  • PVC names do not change. A StatefulSet names each claim <volumeClaimTemplate>-<StatefulSet name>-<ordinal>. The chart names the StatefulSet qdrant through qdrant.fullnameOverride, so the new StatefulSet requests the same claims and binds the existing volumes.
  • Deleting the StatefulSet keeps its PVCs. Kubernetes applies the StatefulSet’s persistentVolumeClaimRetentionPolicy. The qdrant chart does not set it, so the default whenDeleted: Retain applies. The StorageClass reclaimPolicy plays no part, because the PVCs are never deleted and the volumes are never released.
  • helm uninstall keeps them too. Helm deletes only the objects in the release manifest, and PVCs that a StatefulSet creates from its templates are not in the manifest.
Do not delete the qdrant StatefulSet with --cascade=orphan. That option keeps the old pod running, but the new StatefulSet has a different selector and cannot adopt it, so it cannot start its own pod either.

Before the cutover: check the volumes

1

Confirm the claim names

Expect qdrant-storage-qdrant-0 and, if snapshots were on, qdrant-snapshots-qdrant-0.
2

Check the retention policy

An empty value or Retain is safe. If the value is Delete, the PVCs are deleted together with the StatefulSet. Change the policy to Retain before the cutover:
3

Compare sizes and StorageClass

Compare your existing claims with qdrant.persistence and qdrant.snapshotPersistence. The StatefulSet reuses an existing claim as is, whatever the template says, but matching values keep the release definition accurate.
4

Decide on a snapshots claim

If your installation never had a snapshots claim, decide whether you want one. With qdrant.snapshotPersistence.enabled: true, the default, the chart creates a new 30Gi claim. Set it to false to keep the current layout.

What if your claim names are different?

If the first check shows other names, for example because the qdrant StatefulSet carried a release prefix, the new StatefulSet does not find your volumes. It creates new, empty claims instead, and the AI services lose their indexed collections. Before the cutover, do one of the following, and test it in a non-production environment first:
  • Set qdrant.fullnameOverride to the existing StatefulSet name, and set global.flowx.qdrant.servers.flowx.grpc.host to that name’s headless Service, {existing-name}-headless, so that both the claim names and the service address match. The chart default is qdrant-headless.
  • Take a qdrant snapshot of each collection, migrate with new claims, and restore the snapshots afterwards.

After the cutover

Confirm that the new pod uses the existing claims and that no new claim appeared:
The AGE column of each claim must show its original age.

Other behavior changes

Review these changes against your installation before the cutover. Most need no action.

Run the cutover

The cutover replaces the old releases with the flowx-ai release. How you carry it out depends on your deployment tooling: this section describes what the cutover must achieve. Complete Convert your values, Migrate S3 buckets, the checks in PVC behavior, and the review of Other behavior changes first.

Prepare

1

Freeze the namespace

Freeze all other changes to the namespace, so that the cutover changes only the charts.
2

Take the backups

Take the backups listed in Prerequisites.
3

Keep the old definitions

Keep a copy of the old releases’ values and rendered manifests. You need them to roll back.
4

Rehearse

Measure how long the cutover takes in a test environment, and size the maintenance window from it.

What must the cutover do?

1

Stop the old releases from managing their workloads

Make sure nothing recreates the old Deployments or StatefulSet while you replace them, for example an automated sync or a scheduled pipeline.
2

Remove the old Deployments and the qdrant StatefulSet

Their selectors cannot change, so they must be deleted before the new release can create its own. The outage starts here.
  • Remove only the platform workloads. If your databases, Kafka, or object store run in the same namespace, make sure their StatefulSets are not caught by the same operation.
  • Delete the qdrant StatefulSet with normal cascading deletion, not as an orphan. See PVC behavior. If the flowx-ai release keeps the release name of your ai-platform release, the qdrant selector does not change and the StatefulSet can stay.
3

Hand over or remove the other objects of the old releases

Services, Ingresses, ServiceAccounts, ConfigMaps, and RBAC objects keep their names in flowx-ai, but Helm refuses to install an object that another release owns. Either remove them with the old releases, or transfer their ownership to the new release.Helm reads ownership from the annotations meta.helm.sh/release-name and meta.helm.sh/release-namespace and the label app.kubernetes.io/managed-by: Helm. To hand an object over, set the two annotations to the flowx-ai release name and namespace.
4

Preserve what the new release does not create

If the old releases created Secrets or ConfigMaps through their values that your services still need, recreate them outside the old releases, or make sure your flowx-ai values create them.
5

Install the flowx-ai release

Install it with your new values. The outage ends when every Deployment is available and the qdrant pod has reattached its volumes.
6

Remove objects that changed name

The release ConfigMap flowx-release is replaced by flowx-ai-release, and the data-sync Job gets a new name that includes the chart version. Jobs are immutable, so the old data-sync Job is not updated in place. After the cutover, delete the old objects if your tooling does not prune them.
With plain Helm, the simplest cutover is: recreate outside Helm any Secrets the old releases created, run helm uninstall for each old release (the qdrant claims are kept), then run helm install {your-release-name} {flowx-ai-chart-reference} --version {chart-version} -n "$NS" -f values-flowx-ai.yaml.
Do not leave a force-replace or recreate option turned on permanently in your tooling to get through the removal step. It would delete and recreate workloads on every later deployment, not only during the cutover.

Verify the migration

Run these checks right after the cutover, and again after the first day of normal use:
  • Every Deployment is available, and only the services of your enabled groups run: kubectl -n "$NS" get deploy.
  • No workload from an old release remains: kubectl -n "$NS" get deploy,statefulset -L app.kubernetes.io/name,app.kubernetes.io/instance shows flowx-ai on every platform workload and qdrant on the qdrant StatefulSet, all with your release name as the instance.
  • The qdrant pod uses the original claims. See After the cutover.
  • The bucket variables match the names you set. See Step 3: Verify the bucket names after the cutover.
  • You can sign in to FlowX Designer and to a deployed app.
  • A process instance starts, and its UI updates in real time. This exercises events-gateway.
  • A file uploaded before the migration opens, and a new upload succeeds.
  • If AI groups are on, an AI feature answers, for example a chat through ai-gateway or a knowledge base query.
  • Scheduled jobs run at their next trigger.
  • The service logs show no bucket not found, 401, 403, or connection errors that were not there before.
  • Your monitoring still finds the services. Dashboards, alerts, and scripts that select on app.kubernetes.io/name=<service> must now select on app.kubernetes.io/component=<service>.

Roll back

A rollback crosses the same selector change in the other direction, so it is also a delete and recreate. A Helm release history rollback cannot do it, because the old and new workloads belong to different releases. The qdrant PVCs were never deleted, so the old releases reattach them. If the new services changed data that the old versions cannot read, restore the backup you took before the window.
1

Remove the flowx-ai release

Stop your tooling from managing the flowx-ai release, then run helm uninstall for it, or remove its workloads and the objects it owns. The qdrant claims are kept. If the release installed the SpiceDB operator and cluster, they are removed with it: make sure the old releases bring back the SpiceDB setup you ran before.
2

Restore the datastores if needed

Restore PostgreSQL, MongoDB, and the object store from the backup.
3

Reinstall the old releases

Use their previous values, at the chart versions you ran before.
4

Check qdrant

Confirm that the qdrant pod reattached its claims. If you need to restore the qdrant collections, restore them from the snapshots now, while qdrant is running.
Files written while flowx-ai was running go to the buckets that its values named. If those names differed from the old ones, the old releases cannot see those files after a rollback. Carrying over the bucket names as described in Migrate S3 buckets avoids this. document-plugin and integration-designer also stored new files in date-partitioned paths. Test the rollback in a non-production environment before you rely on it.
Keep the old values and manifests until you have signed off the migration.

Troubleshooting

Your values still contain the devtime or runtime key of the ai-platform umbrella chart. Replace them with groups.devtime.enabled, groups.runtime.enabled, and services.<name>.enabled, as described in How do the umbrella flags map?.
A service has both the old minio S3 entry and the new main entry. Move the settings to component.s3.main and remove the minio entry.
An object from an old release still exists, and Helm will not take it over. Remove it, or hand it over by setting the meta.helm.sh/release-name and meta.helm.sh/release-namespace annotations to the flowx-ai release. See What must the cutover do?.
You ran helm upgrade against an existing Deployment or StatefulSet whose selector the new chart changes. Delete the old workload first, as described in What must the cutover do?.
A bucket name or prefix did not carry over. Compare the values from Step 1: Find the names in use with the running Deployments, set the missing names, and upgrade the release. Files stored under the old name are still in the old bucket.
The new StatefulSet created new claims instead of reattaching yours. Check the claim names as described in What if your claim names are different?, or restore the collections from your qdrant snapshots.

AI Platform setup

AI services, configuration, and deployment

Qdrant setup

Vector database configuration

SpiceDB

Authorization service setup

5.9.6 release notes

Upgrade notes for FlowX.AI 5.9.6
Last modified on October 21, 2026