skip to content

When a Helm chart has subcharts, are the parent's resources applied before the subcharts'?

level: middleimportance: should knowfreq 46%

answer

  1. How many releases does the chart create?
  2. Rendering happens before ordering
  3. The sort key does not include the chart
  4. Manifests from all charts merge into one list
  5. Kind decides; chart boundaries are invisible

basics

~20 s

No. Helm renders the parent and every subchart into one flat set of manifests and applies the fixed kind sort across all of them together, so a subchart's Service goes before the parent's Deployment. Charts are not sequenced.

solid answer

~40 s

A Helm release is one unit, not one release per chart. Parent and subchart templates are all rendered first, their manifests merged into a single list, and the kind sort applied to that whole list — so ordering is by kind across chart boundaries, never by chart. A subchart `ServiceAccount` precedes the parent `Deployment` because ServiceAccount precedes Deployment, not because of who owns it. The order of entries under `dependencies:` in `Chart.yaml` governs value merging and rendering, not apply order, and there is no field that says "install this subchart first". If a subchart genuinely must be up before the parent's workload, the tools are the `helm.sh/hook` annotation family, designing the workload to tolerate the dependency being absent, or splitting the subchart into its own release.

code

bash · 8 lines
bash
# Kinds from parent and subchart are interleaved, not grouped by chart
helm template batch ./batch-job | grep -E '^kind:|^# Source:'
# # Source: batch-job/templates/serviceaccount.yaml
# kind: ServiceAccount
# # Source: batch-job/charts/db/templates/secret.yaml
# kind: Secret
# # Source: batch-job/templates/configmap.yaml
# kind: ConfigMap

go deeper

for a junior

Remember the headline: a chart and its subcharts install as a single release, and everything is sorted together by kind. There is no per-chart step you can observe or control.

for a middle

Be able to walk the mechanics: build the tree, merge values, render everything, flatten to one manifest list, then sort by kind. Explain that dependency declaration order is a render-time concern, not an apply-time one.

for a senior

Show where the flat model bites — a CRD and its custom resource in one release, or a dependency a workload cannot retry into — and name the real remedies: a crds/ directory, hooks, or splitting into separate releases.

for a principal

Own the packaging decision: when an umbrella chart's flat ordering stops being adequate, argue for splitting the platform into ordered releases driven by something above Helm, and be explicit about the atomicity and rollback you give up.

### One release, one sorted list The instinct behind this question is that a dependency should be installed before whatever depends on it — the way a package manager installs libraries before the application. Helm does not work that way. A chart with subcharts still produces exactly **one** release: one release record, one revision number, one stored manifest, one uninstall. The subcharts are not sub-releases and they are not applied as separate steps. Mechanically, Helm builds the full chart tree (the parent plus everything under `charts/`), computes the merged values, renders every template in the tree, and collects the resulting documents into a single flat list of manifests. Only then does the kind sort run — over the whole list at once. The sort key is the manifest's `kind`; nothing in the sort records which chart a manifest came from. So a subchart's `ConfigMap` is applied before the parent's `Deployment`, and the parent's `ConfigMap` is applied before the subchart's `Deployment`, purely because ConfigMap outranks Deployment in the table. ### A worked example Take a batch-job chart that packages a queue-worker plus a small database subchart. The rendered set might contain the parent's ServiceAccount, ConfigMap and Deployment, and the subchart's Secret, Service, PersistentVolumeClaim and StatefulSet. Helm applies: both ServiceAccounts, the Secret, both ConfigMaps, the PVC, both Services, the parent Deployment, then the subchart StatefulSet — interleaved by kind, with the two charts' objects shuffled together. Notice that the database's StatefulSet is submitted *after* the worker Deployment, because StatefulSet sits after Deployment in the table. The dependency relationship in `Chart.yaml` did nothing to prevent that. ### What dependency declaration order does control The `dependencies:` list in `Chart.yaml` is real and it does matter — just not here. It decides which subcharts are fetched and vendored, and it participates in how values are merged and how templates and named templates from the tree are assembled before rendering. It is a *build and render* concern. By the time the kind sort runs, that structure has been flattened away and Helm is looking at a list of manifests with kinds. ### Why Helm chose this Per-chart sequencing sounds better until you consider what it would cost. Applying chart A fully before chart B means either applying without waiting — in which case you have gained nothing over the flat sort — or waiting for chart A's workloads to be ready, which turns every install into a serial pipeline whose duration is the sum of its parts and whose failure modes multiply. Helm instead submits the whole desired state quickly and lets the cluster's controllers converge, which is the Kubernetes-native way to get there: the queue-worker whose database is not ready yet crash-loops or backs off for a few seconds and then succeeds. ### When flat ordering genuinely hurts It hurts when the dependency is not something a workload can retry into. A subchart that installs a CustomResourceDefinition while the parent renders a custom resource using it is the classic case: the CRD must exist and be served before the custom resource is accepted, and a retry does not happen because the *apply* failed, not the pod. The standard answers are to move the definitions into a `crds/` directory, which is installed ahead of the sorted manifests, or to split the dependency into a release of its own that is installed first. For softer cases — an admission or gateway component that must exist before the workload it fronts — the tools are the `helm.sh/hook` annotation family, which lifts a manifest out of the sorted set entirely, or a workload written to tolerate the dependency being absent for the first few seconds. ### The takeaway to say out loud Order in a Helm release is a property of kinds, not of charts. If somebody asks you to "install the subchart first", the honest answer is that the chart format has no way to express that, and the design has to move: separate releases, a `crds/` directory, hooks, or a workload that retries.

  • Does the order of entries under `dependencies:` in Chart.yaml influence anything at all?
    Yes, but not apply order. It is part of how the chart tree is built and how values and templates are assembled before rendering. Once rendering finishes, Helm holds a flat list of manifests and sorts it by kind, with no record of which chart produced which document.
  • A subchart ships a CustomResourceDefinition and the parent renders a custom resource using it. Why can that fail on a fresh install?
    Both are in the same sorted list, so the CRD is applied moments before the custom resource with no wait in between; if the API server has not yet started serving the new kind, the custom resource is rejected. Putting the definition in a `crds/` directory, which is installed ahead of the sorted manifests, or splitting it into its own release, removes the race.
  • Would installing each subchart as its own release fix ordering?
    It would give you real sequencing, because you control when each install runs and whether you wait for it. The cost is that you no longer have one atomic unit: separate revision histories, separate rollbacks, and an orchestration layer above Helm that has to remember the order.

It is like sorting a merged deck of cards by rank: once two decks are shuffled together, no card remembers which box it came from.

saying these in an interview costs you the question

  • Says each subchart is installed as its own release
  • Claims dependency order in Chart.yaml sequences the apply
  • Thinks the parent chart is always applied last
  • Believes Helm waits for a subchart before continuing
  • Assumes a subchart's CRD is safely established before its custom resources

context