Helm range without leaving global scope
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
In Helm templates, range changes the meaning of the dot value. Inside the loop, . becomes the current item, which is why many templates suddenly lose access to .Values, .Chart, or .Release. The fix is to keep a reference to the root context and use it explicitly.
Why Scope Changes Inside range
Helm templates use Go's text templating rules. The current context is stored in .. When you write a range, Helm rebinds . for each element in the collection.
That means this template is fragile:
Inside the loop, . is now a port value like 8080, not the original top-level chart context. So .Values.appName no longer exists there.
Use $ for the Root Context
Helm exposes the original root as $. You can access global values from anywhere in the template by using $.Values, $.Release, or $.Chart.
That is the most direct answer to "how do I range without leaving global scope?" You do not stop scope from changing. You keep a pointer to the global scope and reference it when needed.
Save the Root in a Named Variable
For more complex templates, many chart authors save the root context into a variable for readability.
This becomes especially useful when nested range and with blocks appear in the same file.
Example With Maps and Nested Objects
Suppose values.yaml contains:
A working template could be:
Inside the loop, .name and .port come from the current port item, while $root.Values.appName still reads the global chart value.
with Has the Same Kind of Scope Change
This problem is not unique to range. with also changes the meaning of ..
The same rule applies: use . for the local narrowed object, and use $ or a saved root variable when you need the global context.
When to Use Local Variables
If a value is used repeatedly, store it once.
This avoids long expressions and makes the template easier to review.
Common Pitfalls
A common mistake is assuming range iterates without changing .. In Helm, that assumption breaks many templates immediately.
Another mistake is mixing . and $ carelessly in nested loops. If the template is hard to read, save the root into a named variable and use clear local names.
Chart authors also sometimes try to solve the problem by copying values into each item. That is unnecessary if the only issue is scope. Root references already solve it cleanly.
Summary
- In Helm,
rangerebinds.to the current loop item. - Use
$to access the original root context from inside the loop. - Saving
.into a variable like$rootimproves readability in complex templates. - The same scoping rule applies to
withblocks. - The goal is not to stop scope changes, but to reference the correct scope explicitly.
Related reading
- Helm rollback to previous release
- helm sentry created additional load balancer
- Helm Set Docker Image Tag Dynamically
- Helm template arithmetic division
- helm templating with toYaml
- Helm upgrade doesn't pull new container
- Helm UPGRADE FAILED cannot patch ... with kind Job, by update field image
- Helm V3 - Cannot find the official repo

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.