Terraform templatefile Function: Purpose, Usage, and Implementation Details
The templatefile function reads an external file, parses it as a Terraform template using interpolation syntax ${...}, and renders it with a supplied map of variables, returning the result as a string.
The templatefile function is a core built-in within the HashiCorp Terraform language that enables dynamic configuration generation by separating template content from infrastructure logic. According to the hashicorp/terraform source code, this function is implemented in the internal language runtime and provides a safe, recursion-guarded mechanism for rendering external text files with Terraform's native expression engine.
What Is the Terraform templatefile Function?
The templatefile function serves as a bridge between static file content and dynamic Terraform values. When invoked, it performs three distinct operations: it resolves the provided file path relative to the current working directory (or module directory for child modules), parses the file contents using Terraform's HCL interpolation syntax, and substitutes variable references with values from a supplied map.
The function is defined in internal/lang/funcs/filesystem.go and registered in the global function map within internal/lang/functions.go. Its behavior is documented for human consumption in internal/lang/funcs/descriptions.go, with comprehensive test coverage in internal/lang/funcs/filesystem_test.go and internal/lang/functions_test.go.
How templatefile Works Internally
Factory Creation and Registration
The implementation begins with funcs.MakeTemplateFileFunc, which constructs a closure capturing the base directory context and a lookup map of available functions. This factory pattern allows the function to maintain awareness of the calling module's filesystem context while remaining isolated from the global state. The function becomes available to Terraform expressions after being injected into the evaluation context during the language initialization phase.
Argument Validation and File Loading
The function requires exactly two arguments: a path string specifying the file location, and a vars map containing variable bindings. Path resolution follows Terraform's standard semantics: relative paths resolve against the current working directory or the calling module's directory, while absolute paths are used as-is. The actual file reading occurs via os.ReadFile, with filesystem errors converted into Terraform evaluation errors that halt execution with descriptive messages.
Template Rendering and Recursion Guard
Once loaded, the raw file content passes through Terraform's HCL expression parser, enabling full access to interpolation features including conditionals, loops, and function calls. Critically, the implementation includes a recursion prevention mechanism: before rendering, the function creates a modified copy of the function lookup map where templatefile is replaced with a placeholder that returns an error if invoked. This design prevents infinite loops and keeps the evaluation model predictable by blocking nested templatefile calls.
Correct Usage and Syntax
The templatefile function follows this signature:
templatefile(path, vars)
path: A string containing the relative or absolute path to the template file.vars: An object/map where keys become variable names available inside the template.
Basic Usage Example
Create a template file named hello.tmpl:
Hello, ${name}!
Reference it in your configuration:
locals {
rendered = templatefile("${path.module}/hello.tmpl", {
name = "Jodie"
})
}
output "greeting" {
value = local.rendered
}
This outputs: Hello, Jodie!
Using Complex Values and Functions
Templates can invoke Terraform functions and accept complex data structures. Consider an IAM policy template:
# policy.tmpl
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": ${jsonencode(actions)},
"Resource": "${resource_arn}"
}
]
}
Supply the variables:
locals {
policy = templatefile("${path.module}/policy.tmpl", {
actions = ["s3:GetObject", "s3:PutObject"]
resource_arn = "arn:aws:s3:::my-bucket/*"
})
}
The jsonencode function executes during template rendering because the evaluation context includes the complete Terraform function library.
Important Limitations and Safety Features
Recursion Blocking
The source code explicitly prevents recursive templatefile calls to avoid infinite loops and stack overflow conditions. If a template attempts to call templatefile internally, Terraform returns an error:
# rec.tmpl (deliberately broken)
${templatefile("rec.tmpl", {})}
output "bad" {
value = templatefile("${path.module}/rec.tmpl", {})
}
This configuration produces:
Call to function "templatefile" failed: cannot recursively call templatefile from inside another template function.
This safeguard is implemented in internal/lang/funcs/filesystem.go by shadowing the templatefile entry in the function map during template evaluation.
Summary
- Purpose:
templatefilerenders external text files using Terraform's interpolation syntax, enabling dynamic configuration generation. - Location: Core implementation resides in
internal/lang/funcs/filesystem.go, with registration ininternal/lang/functions.go. - Safety: The function blocks recursive calls to prevent infinite loops and maintain evaluation predictability.
- Capabilities: Supports full HCL expression syntax including conditionals, loops, and built-in function calls like
jsonencode. - Path Handling: Resolves relative paths against the current module directory and absolute paths as-is.
Frequently Asked Questions
Can templatefile be used to render templates that call other templates?
No. As implemented in the Terraform source code, templatefile explicitly blocks recursive invocation. If a template contains a ${templatefile(...)} reference, the evaluation will fail with an error stating that recursive calls are prohibited. This limitation prevents infinite loops and ensures deterministic evaluation.
What happens if the template file contains syntax errors?
Terraform parses the template file using the same HCL expression engine used for .tf files. If the template contains invalid syntax, the function returns an evaluation error pointing to the specific line and column of the failure. Filesystem errors, such as missing files or permission issues, are also surfaced as Terraform errors with descriptive messages.
How does templatefile handle file paths in modules?
When called from within a module, templatefile resolves relative paths against that module's directory, not the root module. This allows reusable modules to ship with their own template files. Absolute paths (those starting with / on Unix systems or drive letters on Windows) are used without modification.
Is there a performance difference between templatefile and the template_file data source?
The templatefile function is generally preferred over the deprecated template_file data source because it executes during the configuration phase without creating a managed resource. The function implementation uses direct file I/O via os.ReadFile and renders immediately, avoiding the overhead of provider plugin communication and state management associated with data sources.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s https://instagit.com/install.md