skip to content

How would you choose between a Helm chart and a typed generator such as cdk8s or jsonnet?

level: principalimportance: nice to knowfreq 33%

answer

  1. Producing YAML and tracking it are separate
  2. Ask who installs the software
  3. A generator emits, it does not track
  4. The toolchain becomes part of delivery
  5. Hybrids exist: generate, then package

basics

~20 s

Split the decision in two: who produces the YAML, and who tracks what was applied. A generator replaces only the first. If the artefact leaves your team, a chart is the interchange format; if it never does and the logic is real programming, a generator usually wins.

solid answer

~40 s

Helm does two jobs at once — rendering templates and maintaining a release — while cdk8s and jsonnet do only the first, emitting manifests that something else must apply and track. So the question is really two questions. On rendering: a generator gives you a real language with functions, types, tests and refactoring tools, which is worth a lot when the logic is genuinely complex; templating gives you a smaller thing anyone can read without a toolchain. On lifecycle: if you drop Helm entirely, you also drop history, rollback and uninstall tracking, so decide deliberately whether your delivery system already provides those. The decider is usually distribution. External consumers expect a versioned chart with a `values.yaml` contract, published to a repository or referenced by `oci://`; nobody outside your team will install your TypeScript.

code

bash · 7 lines
bash
# generator: produces manifests, tracks nothing
cdk8s synth --output dist/
kubectl apply -f dist/

# hybrid: generated manifests become a chart's static templates
cdk8s synth --output chart/templates/
helm upgrade --install telemetry-gateway ./chart -n telemetry

go deeper

for a junior

Know that cdk8s and jsonnet produce Kubernetes manifests from code or a data language, and that unlike Helm they stop there — something else still has to apply the output to a cluster.

for a middle

Be able to explain what is lost when a generator replaces a chart: no release record, no history or rollback, no hook ordering, and no packaged artefact anyone outside your team can install.

for a senior

Argue the tradeoff concretely for a real system: where the logic genuinely needs a language, how review stays honest once YAML is generated, and which parts of the estate keep Helm because they consume other people's charts.

for a principal

Own the estate-wide standard and its boundary. Decide what is generated, what is charted, what is literal, price the toolchain and staffing consequences, and be prepared to defend running more than one approach on purpose.

### Two jobs, not one Every discussion of Helm alternatives goes wrong in the same place: treating "how manifests are produced" and "how manifests are installed and tracked" as one decision. Helm bundles them. `helm install` renders a chart and then records a release, which is what makes `helm history`, `helm rollback` and `helm uninstall` possible. cdk8s and jsonnet do not compete with the second half at all — they emit YAML to disk. Something else then applies it: a person, a pipeline, or a continuous-reconciliation system such as Argo CD or Flux. So the first move in this decision is to say out loud which of the two jobs you are actually replacing. That framing immediately produces the hybrid options that teams miss. You can generate manifests and commit them as a chart's static `templates/` directory, keeping Helm purely for the release lifecycle while the interesting logic lives in code with tests. You can generate manifests and let a reconciliation agent own applying and pruning, with no Helm at all. Or you can keep the chart and accept the templating. ### The distribution decider The single strongest input is who installs the software. If the answer includes anyone outside the team that wrote it — other business units, customers, the open-source public — the chart wins, and not because it is a better abstraction. It is the *interchange format*: a versioned `.tgz` with a documented `values.yaml` contract, optionally a `values.schema.json` for validation, dependency declarations in `Chart.yaml`, distribution through a repository with an `index.yaml` or by `oci://` reference, and optional provenance in a `.prov` file. Every one of those is a promise an installer can rely on without adopting your language. A generator's output is a snapshot; its *source* is a program in your chosen language with your chosen dependencies, and asking an external consumer to run that is asking them to adopt your toolchain to configure your software. If the artefact never leaves the team, that entire argument evaporates and the decision becomes ergonomic. ### What the generator actually buys A real language brings functions with parameters, types (in the case of cdk8s, generated from the Kubernetes API schemas), unit tests over the produced objects, IDE navigation, and refactoring that a text templater cannot offer. When the logic is genuinely computational — deriving one object's fields from another's, enforcing invariants across a set of objects, generating a variable number of related objects — that gap is large. Templating over YAML is untyped string substitution; a wrong branch can emit a document that is structurally broken or valid but wrong, and only rendering reveals it. ### What it costs, in the terms a lead has to own - **Toolchain in the delivery path.** A language runtime, a dependency manifest and its own supply chain now sit between a change and a manifest. That is a build step to maintain, cache and secure. - **Review moves.** Reviewers read code, and the YAML that actually ships becomes a generated artefact. Either you commit generated output and review the diff, or you accept that pull requests no longer show what changes in the cluster. - **Staffing and onboarding.** Charts have a large pool of people who already know them. A jsonnet estate or a cdk8s estate needs people willing to learn it, and the bus factor of the person who designed the abstractions is a real risk. - **Model lag.** A typed generator's model of the Kubernetes API is a generated artefact with its own release cadence; a new field may need an escape hatch until the model catches up. Templating over raw YAML never has this problem, which is an underrated advantage. - **Ecosystem.** Third-party software is overwhelmingly distributed as charts. Choosing a generator internally does not remove Helm from the cluster; you will still install other people's charts, so the team maintains two mental models rather than one. ### A decision I would defend For an 18-chart umbrella maintained by one platform team, where the abstraction pressure is real and no outsider installs anything, I would move the generation of the platform's own workloads into a typed generator, commit the rendered manifests so reviews stay honest, and keep Helm for third-party software and for anything the platform publishes to other teams. That is deliberately not a single-tool answer. The failure mode to avoid is mandating one medium estate-wide and then discovering that half the estate is paying for a capability it does not use — either a chart's release machinery nobody exercises, or a generator's toolchain maintained for manifests that never branch. ### What makes this a principal-level answer Naming the two jobs separately, identifying distribution as the decider rather than aesthetics, pricing the organisational costs alongside the technical ones, and being willing to run more than one approach with a stated boundary between them.

  • If a team adopts a generator but still wants helm rollback, what does that setup look like?
    Generate the manifests, commit them as a chart's `templates/` directory with no template actions in them, and install that chart. Helm then does nothing clever at render time but still records each revision, prunes resources that left the chart, and supports history, rollback and uninstall. The abstraction lives in tested code; the lifecycle stays with Helm. The price is a build step producing a committed artefact.
  • Does choosing a generator internally let a platform team stop knowing Helm?
    No. Third-party software is distributed overwhelmingly as charts, so the cluster will keep receiving Helm releases regardless of how your own workloads are produced. The team still needs to read a vendor chart's values contract, understand its hooks and CRD handling, and operate its releases. Any plan that assumes Helm expertise can be dropped is underestimating the ongoing cost.
  • How would you keep pull-request review honest once manifests are generated rather than written?
    Commit the generated output and have CI regenerate and diff it, failing when the committed artefact does not match the source. Reviewers then see both the code change and the exact manifest change it causes. Without that, the reviewed artefact and the applied artefact diverge, and the team loses the one property that made declarative manifests reviewable in the first place.

saying these in an interview costs you the question

  • Treating a generator as a replacement for release tracking
  • Recommending one medium for an entire estate unconditionally
  • Ignoring that external consumers expect an installable chart
  • Assuming a generator removes the need to operate Helm at all
  • Forgetting that generated YAML makes review artefacts diverge
  • Pricing only the tooling and not the staffing cost

context