Helm
templates
Kubernetes
_helpers.tpl
DevOps

Helm _helpers.tpl Calling defined templates in other template definitions

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

In Helm, _helpers.tpl is where you define reusable template snippets such as chart names, labels, and common metadata blocks. The key mechanism is simple: define a helper with define, then call it from another template with include or template, passing the context object that the helper needs.

Core Sections

Defining a helper in _helpers.tpl

Helpers are named templates. A common example is a helper that builds a chart-specific full name.

gotemplate
{{- define "mychart.fullname" -}}
{{- printf "%s-%s" .Release.Name .Chart.Name | trunc 63 | trimSuffix "-" -}}
{{- end -}}

The string "mychart.fullname" is the helper name. Namespacing helpers with the chart name is important because Helm loads all templates into one namespace during rendering.

Calling a helper from another template

The most common way to call a helper is include.

gotemplate
1apiVersion: v1
2kind: Service
3metadata:
4  name: {{ include "mychart.fullname" . }}

The final . passes the current context into the helper. Without that context, the helper cannot read values such as .Release.Name, .Chart.Name, or .Values.

Calling one helper from another helper

You can also call a helper from inside another helper definition. This is a very common pattern for labels.

gotemplate
1{{- define "mychart.name" -}}
2{{- .Chart.Name -}}
3{{- end -}}
4
5{{- define "mychart.labels" -}}
6app.kubernetes.io/name: {{ include "mychart.name" . }}
7app.kubernetes.io/instance: {{ .Release.Name }}
8{{- end -}}

Then in a manifest:

gotemplate
metadata:
  labels:
    {{- include "mychart.labels" . | nindent 4 }}

This is the normal answer to "how do I call a defined template inside another definition?" You use include and pass the right context again.

include versus template

Both include and template render a named template, but include is more convenient because it returns a string that can be piped through functions such as indent, nindent, trim, or quote.

gotemplate
{{ include "mychart.labels" . | nindent 4 }}

That is why most modern Helm charts prefer include for helper usage inside YAML. template still works, but it is less composable in pipelines.

Passing custom data with dict

Sometimes a helper needs more than the default dot context. In that case, build a small object with dict.

gotemplate
1{{- define "mychart.image" -}}
2{{ .repository }}:{{ .tag }}
3{{- end -}}
4
5image: {{ include "mychart.image" (dict "repository" .Values.image.repository "tag" .Values.image.tag) }}

This is useful when the helper should receive only the data it needs instead of the entire release context.

Indentation matters in YAML

A frequent Helm issue is not the helper itself, but where the rendered text lands in the output. Helpers that render YAML fragments usually need nindent so the final manifest stays valid.

gotemplate
metadata:
  labels:
    {{- include "mychart.labels" . | nindent 4 }}

Without the right indentation, the template may render syntactically invalid YAML even though the helper logic itself is correct.

Common Pitfalls

  • Defining helpers with generic names and colliding with templates from other charts or subcharts.
  • Calling a helper without passing the expected context object, which makes .Values, .Chart, or .Release unavailable.
  • Using template where include plus nindent would make YAML composition easier.
  • Forgetting indentation and producing invalid rendered manifests even though the helper output looks correct by itself.
  • Letting helpers become mini-programs full of business logic instead of keeping them focused on reusable formatting and naming.

Summary

  • Put reusable Helm snippets in _helpers.tpl with define.
  • Call helpers from manifests or other helpers with include "name" ..
  • Pass the right context every time, or build a custom one with dict.
  • Prefer include when you need to pipe the result through indent or other functions.
  • Keep helper names namespaced and their responsibility small so charts stay readable and composable.

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track 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.

Practice system design

All Rights Reserved.