At some point, hardcoding values in Terraform starts to feel wrong. Maybe you're generating multiple config files, or passing slightly different values into similar resources. That’s where Terraform’s templatefile function quietly becomes one of the most useful tools in your workflow.
Instead of duplicating blocks or stitching strings together, templatefile lets you generate files dynamically using variables. It’s simple, but once you start using it, you’ll wonder how you managed without it.
What the templatefile Function Actually Does
At its core, templatefile reads a file from disk and renders it using variables you provide.
Here’s the basic syntax:
1templatefile(path, vars)- path: Path to your template file
- vars: A map of variables injected into the template
The template itself uses Terraform’s expression syntax (${}) to interpolate values.
A Quick Example First
Let’s say you want to generate a configuration file for an application.
Template file: config.tmpl
1app_name = "${app_name}"
2environment = "${environment}"
3port = ${port}Now in your Terraform code:
1locals {
2 config_content = templatefile("${path.module}/config.tmpl", {
3 app_name = "billing-service"
4 environment = "prod"
5 port = 8080
6 })
7}This produces a fully rendered string you can use anywhere — for example, writing to a file or passing into a resource.
Generating Real Files with local_file
A common pattern is pairing templatefile with the local_file resource:
1resource "local_file" "app_config" {
2 filename = "./generated/config.conf"
3 content = local.config_content
4}This approach is clean and avoids manually maintaining config files outside Terraform.
Why Developers Reach for templatefile
Here’s where things get interesting. This function isn’t just about convenience — it solves real problems:
- Eliminates duplication across similar configurations
- Improves readability compared to inline string concatenation
- Separates logic from structure (Terraform vs config files)
- Makes scaling easier when handling multiple environments
A common mistake developers make is trying to build long JSON or YAML blobs directly inside Terraform. It works… until it becomes unreadable. Templates fix that immediately.
Working with Loops and Conditionals
Templates support Terraform’s expression syntax, including loops and conditionals.
Example: Rendering a list
1servers = [
2%{ for server in servers }
3 "${server}",
4%{ endfor }
5]And the Terraform code:
1locals {
2 rendered = templatefile("servers.tmpl", {
3 servers = ["web-1", "web-2", "web-3"]
4 })
5}This produces a properly formatted list in the output.
Conditionals example:
1%{ if enable_logging }
2logging = true
3%{ else }
4logging = false
5%{ endif }This makes your templates flexible without complicating your Terraform code.
Using templatefile for Cloud-Init Scripts
One of the most practical use cases is generating cloud-init or user data scripts.
1resource "aws_instance" "example" {
2 ami = "ami-123456"
3 instance_type = "t2.micro"
4
5 user_data = templatefile("${path.module}/user_data.sh", {
6 app_port = 3000
7 env = "staging"
8 })
9}This keeps your scripts readable while still allowing dynamic values.
Handling JSON and YAML Cleanly
If you’ve ever tried writing JSON inline in Terraform, you know it gets messy fast. With templates, you can write natural JSON:
1{
2 "service": "${service_name}",
3 "replicas": ${replicas}
4}Alternatively, for purely structured data, Terraform’s jsonencode() can sometimes be cleaner — but for mixed formatting or human-readable files, templatefile wins.
Gotchas You Should Know
A few things tend to trip people up:
- No implicit variables: Every variable must be explicitly passed
- Path issues: Always use
${path.module}for portability - Trailing commas in loops: Be careful when generating JSON
- Indentation matters: Especially for YAML templates
If something looks off in the output, it’s usually formatting rather than logic.
When Not to Use templatefile
It’s powerful, but not always necessary.
- If you’re generating simple structured data → use
jsonencode() - If there’s no reuse → inline values may be simpler
- If logic becomes complex → consider splitting templates
Think of templatefile as a readability and maintainability tool, not just a feature.
A Pattern That Scales Well
In larger projects, teams often organize templates like this:
- /templates
- app_config.tmpl
- nginx.tmpl
- user_data.sh
Then Terraform modules simply reference them with different variables. This keeps your infrastructure code clean and modular.
Wrapping It Up
The Terraform templatefile function is one of those features that feels optional—until your configuration grows. Then it becomes essential.
It helps you:
- Keep Terraform code readable
- Generate dynamic configs safely
- Avoid duplication across environments
If your current setup involves copy-pasting blocks or wrestling with long strings, this is a good place to simplify things.
When infrastructure starts repeating itself, templates aren’t an optimization — they’re a necessity.