In Helm 4, how does helm template differ from helm install --dry-run=client and --dry-run=server?
answer
- Three previews with different amounts of reality
- One renders offline, one goes through install
- --dry-run stopped being a boolean in Helm 4
- client versus server decides who validates
- --validate deprecated in favour of --dry-run=server
basics
~20 shelm template renders offline and prints YAML. helm install --dry-run=client renders through the install path against your configured cluster but writes nothing. --dry-run=server also sends the manifests to the API server, so schema validation and admission run and nothing is persisted.
solid answer
~50 sAll three preview an install, with increasing amounts of reality. `helm template` is a pure local render: chart plus values in, YAML out, no cluster needed, so it catches template bugs only. `helm install --dry-run=client` goes through the install code path and the client's cluster connection — the render sees the target cluster's discovered API versions — but the manifests are never sent anywhere, so nothing checks their fields. `helm install --dry-run=server` sends them: the API server decodes, defaults, schema-validates and admits the request, then discards it instead of persisting, which is the only way to learn locally that a field name is wrong or a cluster policy will reject the object. In Helm 4 `--dry-run` takes a value (`client` or `server`) rather than being the boolean it was in Helm 3; on `helm template`, `--validate` is deprecated in favour of `--dry-run=server` and the two flags are mutually exclusive.
code
bash · 8 lines# pure local render: no cluster, template bugs only
helm template indexer ./operator-chart -f values-prod.yaml
# install path, nothing written, manifests never leave the client
helm install indexer ./operator-chart -f values-prod.yaml --dry-run=client
# API server decodes, validates and admits the manifests, then discards them
helm install indexer ./operator-chart -f values-prod.yaml --dry-run=servergo deeper
Recall that all three show you YAML without changing the cluster, and that only the server-side form asks Kubernetes whether the manifests are acceptable. Know that --dry-run needs a value in Helm 4.
Explain precisely who does the work in each: local render, install path with cluster discovery, and full API-server request processing that is discarded. Be able to say which class of bug each one can and cannot catch.
Show judgement about where each belongs in a pipeline — an offline render in a stage with no credentials, a server-side dry run as a pre-upgrade gate — and be candid about what a green dry run still does not promise.
Own the tradeoff between preview fidelity and blast radius: how much cluster access a validation stage should hold, whether every environment gets the same gate, and what you do when the only cluster that can validate a change is production.
### Three previews, three different amounts of reality When someone says "let me dry-run it first", they could mean any of three things in Helm, and the three catch different classes of bug. **`helm template`** renders the chart locally and prints YAML. No release is created, nothing is applied, and by default no cluster is contacted. It catches template bugs only: a missing value, a mis-scoped dot, a helper that produced the wrong string. **`helm install --dry-run=client`** takes the same chart through the install code path but stops before writing. It behaves like a real install right up to the apply: the client goes through its normal cluster connection, so in practice it wants a reachable cluster and a valid kubeconfig, and the render sees the target cluster's discovered API versions rather than a built-in default list. What it does not do is send the manifests anywhere for checking — the API server never sees them, so it cannot tell you whether the fields you wrote exist. **`helm install --dry-run=server`** does send them. The manifests go to the API server as a server-side dry run: the request is fully processed — decoded, defaulted, validated against the schema for that resource, and run through admission — and then discarded instead of being persisted. That is the only one of the three that will tell you that you wrote `contaienrs`, that a required field is missing, that a value is the wrong type, or that a cluster-wide admission policy will reject the object. Nothing is created; there is nothing to clean up afterwards. ### The Helm 4 detail that trips people up In Helm 3, `--dry-run` was a boolean: you passed it or you did not. **In Helm 4 it takes a value — `client` or `server`** — so an interview answer that says "just add `--dry-run`" is describing the old CLI. Write the value explicitly and the intent is unambiguous to the next reader as well as to Helm. `helm template` accepts `--dry-run` too, which is how you get the API server to look at an otherwise offline render. Helm 4 also marks `--validate` — the older flag that meant "check the rendered manifests against the API server" — as **deprecated in favour of `--dry-run=server`**, and the two are **mutually exclusive**: passing both on `helm template` is rejected rather than silently resolved, because they are two switches for the same decision and Helm refuses to guess which one you meant. ### Choosing between them Use `helm template` when the question is "what YAML does this chart produce?" — it is fast, offline, scriptable, safe on a laptop with no cluster credentials, and it is the right thing to run in a pipeline stage that has no business holding cluster access. Use `--dry-run=client` when you want the install path itself exercised — release naming, values plumbing, capability discovery against the real target — without a write. Use `--dry-run=server` when the question is "will the cluster accept this?" A render can be flawless YAML and still be nonsense to Kubernetes; only the API server knows its own schema and only the cluster knows its admission rules. This is the check worth wiring into a pipeline before a production upgrade, and it needs a credential with enough access to make the request. ### What a green dry run still does not promise A server-side dry run validates each object in isolation, at this moment, in a cluster whose current state may not be the state at apply time. It does not tell you that a hook Job will succeed, that a workload will become ready, that quota will still allow the objects when the real apply runs, or that an object depending on something the dry run did not actually create will behave. Admission decisions can also depend on the request being a genuine write. Treat a green dry run as "the shapes are right and nothing rejected them out of hand", not as a guarantee about the rollout. ### Practical habit Render offline while you iterate on the chart, because the loop is a second long and needs nothing. Switch to a server-side dry run once the YAML looks right, because that is the cheapest way to learn about a typo'd field or a policy rejection before it becomes a half-applied change. Keep the values flags identical between the two runs — the whole value of the comparison is that only the amount of cluster involvement changed.
- On `helm template`, why does Helm reject `--validate` together with `--dry-run`?They are two switches for the same decision: whether the rendered manifests get checked against a live API server. `--validate` is the older spelling and Helm 4 deprecates it in favour of `--dry-run=server`. Rather than guess which one wins when both appear, Helm marks them mutually exclusive and fails the command, so the intent has to be stated once.
- Does a server-side dry run leave anything behind that needs cleaning up?No. The API server processes the request fully — decode, defaulting, schema validation, admission — and then discards it instead of writing to storage. No object is created, no name is reserved, and no Helm release record is written either, since the client never reaches the persist step.
- A manifest passes `--dry-run=server` and the real install still fails. What can still differ?Plenty. The dry run validates each object in isolation at that moment: it says nothing about whether a workload becomes ready, whether a hook succeeds, whether quota still allows the objects when the real apply runs, or whether an object that depends on something the dry run did not create will work. Admission decisions can also legitimately differ for a genuine write.
saying these in an interview costs you the question
- Says --dry-run in Helm 4 is still a plain boolean flag
- Thinks helm template validates manifests against the API server
- Believes a server-side dry run creates objects to clean up
- Assumes a green dry run guarantees a successful rollout
- Passes --validate and --dry-run together on helm template