Helm 4 Made Me Stop Looking for an Alternative

Helm has been the punchline of Kubernetes packaging for about as long as Kubernetes has been called Kubernetes. Helm 2 had Tiller, an in-cluster component running as cluster-admin that read every chart’s YAML and applied it from inside the cluster — a security horror show that drove half the community to invent its own deployment tooling just to avoid it. Helm 3 finally killed Tiller in 2019 and went client-side, which fixed the worst of it. And then Helm 3 sat there, relatively unchanged, for six years.

In April 2026, Helm 4 finally landed. And after six months of running it on a couple of clusters before I wrote this, I’m willing to say something I haven’t said about Helm before:

It’s now good enough that I’ve stopped looking for an alternative.

This is the honest tour of what changed, what didn’t, and where I still pick something else.

What’s actually in Helm 4

Five changes that matter, in roughly the order they affect me daily:

1. OCI registries are the primary distribution method

This is the headline. helm repo add is no longer the default workflow. No more index.yaml, no more parallel chart-repo infrastructure that exists nowhere else in your stack. Charts now live in the same OCI registries as your container images — GHCR, Harbor, Amazon ECR, Azure Container Registry, Docker Hub, all native:

helm install api oci://ghcr.io/example/charts/api --version 2.4.0

And — this is the part that actually matters for production hardening — install by digest:

helm install api oci://ghcr.io/example/charts/api@sha256:abc123…

When a chart is pinned by digest, supply-chain auditing becomes something you can actually do. Sign the chart with cosign, verify the signature before install, log the digest in your deploy record, done. The OCI ecosystem just absorbed Helm, and Helm is better for it.

2. kstatus is the new readiness watcher

Helm 3’s --wait flag was famously naïve. It knew how to wait for a Deployment, a StatefulSet, a couple of other built-ins, and that was about it. Chart with a Cert-Manager Certificate? Helm thought it was “installed” the moment the Certificate resource existed, regardless of whether the certificate had actually been issued. Chart with an Argo CD Application? Same thing — installed-but-not-actually-ready.

Helm 4 wires in Kubernetes’ upstream kstatus library, which understands the health semantics of dozens of resource types, including most CRDs that follow the conventions. The practical effect: helm upgrade --wait is finally meaningful on real-world charts, not just on the toy ones.

3. Native CRD lifecycle management

Helm 3 had a famously bad story for upgrading CRDs. The community workaround was “install CRDs once, never touch them via Helm again,” which is fine for static charts and a nightmare for charts that ship their own evolving CRDs.

Helm 4 manages CRDs as first-class chart artifacts with safe patching semantics that don’t blow away custom resources mid-upgrade. For anyone who’s ever had a Helm upgrade delete a CRD and take 200 custom resources with it, this is the single most welcome change.

4. WASM plugins replace Go binaries

Helm 3 plugins were Go binaries, which meant compiling per-platform and shipping a different artifact for every OS/arch. Helm 4 plugins are WebAssembly modules: one artifact runs everywhere Helm runs. The plugin author can write in any language that compiles to WASM, the user installs and runs without thinking about architecture, and the sandboxing improves the security story of “I just helm plugin install’d a thing from the internet.”

5. Content-addressed caching, multi-doc values, JSON arguments

Three smaller improvements that compound:

  • Content-addressed cache. Helm’s local chart cache is now keyed on a hash of the chart contents, not on the chart name and version. Two charts with the same name and version but different contents (yes, this happens, especially with private registries) no longer poison each other in the cache.
  • Multi-document values. You can now split a values file into multiple YAML documents in one file, separated by ---. Helm merges them in order. Lets you keep base values, environment overrides, and feature-flag toggles in a single readable file rather than three.
  • JSON arguments. --set-json accepts arbitrary JSON for values that don’t round-trip cleanly through Helm’s strategic string-set parser. The end of --set foo.bar[0].baz=qux Helm syntax for cases where the value is genuinely structural.

What didn’t change — Helm’s persistent annoyance

I owe you the honest version: Helm’s templating is still text-level, not data-level. Go templates render YAML as a string, which means a misplaced indent in a template produces invalid YAML that Helm cheerfully sends to the API server. Complex charts still develop incomprehensible-block-scalar disease. Conditional logic in values still reads like Perl.

The community responses haven’t gone away:

  • Kustomize layered on top of Helm — Helm renders, Kustomize patches the output. Works, two tools to debug.
  • Carvel ytt — a different templating language that operates on YAML as data, not as text. Smaller community, more correct approach.
  • Jsonnet / Tanka — for teams that want a programming language for their manifests. Powerful, niche.
  • Plain manifests + Kustomize — for teams that don’t have package-manager requirements and don’t want Helm at all.

For me, Helm 4 closed the gap enough that I don’t reach for any of these unless a specific chart is genuinely fighting me. That’s the real headline. Not a single feature — a feature density that finally tips the balance.

The three breaking changes worth knowing

Helm 4 has a clean migration guide and most charts work unchanged. Three things to watch for:

  1. helm repo commands are deprecated in favor of helm registry login and OCI URLs. They still work, they print a deprecation notice, they’ll be removed in a future minor.
  2. The Go template API for plugins changed. If you’ve written custom Go-binary plugins, port them to WASM before upgrading.
  3. --wait semantics changed. Because kstatus is stricter, some charts that “installed” cleanly under Helm 3 now correctly report as not-yet-ready. That’s the desired behavior, but it’ll surprise automation that depended on the old leniency.

The official migration guide is thorough. For most users, the upgrade is a morning of friction and then it’s fine.

Where Helm fits in my stack

I run Helm 4 as the packaging layer of my GitOps stack on RKE2. Argo CD does the delivery and reconciliation; Helm is what produces the YAML that Argo applies. (More on that side of the stack in the Argo CD post.)

What I use Helm 4 for, specifically:

  • Upstream charts I trust: Cert-Manager, Ingress, the Prometheus Operator stack, External-DNS, the standard cluster plumbing. These are well-maintained, well-tested, and writing my own manifests for them would be reinventing wheels.
  • OCI-distributed internal charts for shared platform pieces — base monitoring, base ingress rules, the org-wide stuff that gets templated across half a dozen clusters.

What I don’t use Helm for:

  • My own applications. Plain YAML with Kustomize overlays. Less ceremony, easier to reason about, no templating debugging at 3 a.m.
  • One-off resources. A single ConfigMap or a single Secret doesn’t need a chart. kubectl apply -f from a Git path managed by Argo CD is enough.

Closing

Helm 4 isn’t a perfect tool. It’s a good enough tool — the kind of boring, predictable, well-supported infrastructure piece that I want in production. The OCI shift, the kstatus integration, and the CRD lifecycle fix together make it the package manager Helm 3 should have become five years ago. It finally is.

I’ll keep an eye on ytt and on any new alternatives that the community throws at the wall. But for the foreseeable future, when someone asks me how I package Kubernetes applications in 2026, the honest answer is “Helm 4, and I’ve stopped apologising for it.”