Terraform does more than just provision infrastructure. It gives you a powerful set of built-in functions you can use inside your configuration to transform data, format strings, loop over collections, encode values, and much more.
If you have ever written Terraform and found yourself repeating values, hard-coding logic, or wishing you could manipulate a list before passing it to a resource — functions are the answer.
This guide covers every major category of Terraform functions, with real examples you can drop straight into your codebase.
What Are Terraform Functions?
Terraform functions are built-in expressions you can call inside your .tf files to compute or transform values. They are similar to functions in any programming language — you pass in one or more arguments, and they return a result.
You use them inside ${} expressions or directly in resource arguments. Here is a simple example using the upper function:
Terraform functions are evaluated at plan time, not at runtime. That means the result is computed before any infrastructure is created — making your configurations predictable and safe to review.
String Functions
String functions let you manipulate, format, and transform text values. These are among the most commonly used functions in real Terraform configurations.
| Function |
What It Does |
Example |
| upper(string) |
Converts a string to uppercase |
upper("hello") → "HELLO" |
| lower(string) |
Converts a string to lowercase |
lower("WORLD") → "world" |
| trimspace(string) |
Removes leading and trailing whitespace |
trimspace(" hi ") → "hi" |
| trim(string, chars) |
Removes specific characters from both ends |
trim("--env--", "-") → "env" |
| replace(string, search, replace) |
Replaces occurrences of a substring |
replace("a-b-c", "-", "_") → "a_b_c" |
| split(sep, string) |
Splits a string into a list |
split(",", "a,b,c") → ["a","b","c"] |
| join(sep, list) |
Joins a list into a single string |
join("-", ["us","east","1"]) → "us-east-1" |
| format(template, args...) |
Formats a string using a template |
format("app-%s-%d", "web", 1) → "app-web-1" |
| startswith(string, prefix) |
Returns true if string starts with prefix |
startswith("prod-api", "prod") → true |
| endswith(string, suffix) |
Returns true if string ends with suffix |
endswith("main.tf", ".tf") → true |
| substr(string, offset, length) |
Returns a substring |
substr("terraform", 0, 5) → "terra" |
| strlen(string) |
Returns the number of characters in a string |
strlen("hello") → 5 |
Practical String Example: Building Consistent Resource Names
One of the most common uses of string functions is building standardised resource names from input variables:
Numeric Functions
Numeric functions let you perform arithmetic operations and comparisons on number values.
| Function |
What It Does |
Example |
| abs(number) |
Returns the absolute value of a number |
abs(-5) → 5 |
| ceil(number) |
Rounds up to the nearest whole number |
ceil(1.2) → 2 |
| floor(number) |
Rounds down to the nearest whole number |
floor(1.9) → 1 |
| max(numbers...) |
Returns the largest number |
max(3, 7, 2) → 7 |
| min(numbers...) |
Returns the smallest number |
min(3, 7, 2) → 2 |
| pow(base, exponent) |
Raises base to the power of exponent |
pow(2, 8) → 256 |
| signum(number) |
Returns -1, 0, or 1 based on sign |
signum(-4) → -1 |
| log(number, base) |
Returns the logarithm of a number |
log(100, 10) → 2 |
| parseint(string, base) |
Parses a string as an integer |
parseint("FF", 16) → 255 |
Practical Numeric Example: Calculating Instance Counts
Collection Functions
Collection functions are some of the most powerful in Terraform. They let you work with lists, maps, and sets — filtering, merging, transforming, and inspecting them.
| Function |
What It Does |
Example |
| length(collection) |
Returns the number of elements |
length(["a","b","c"]) → 3 |
| contains(list, value) |
Returns true if value is in the list |
contains(["dev","prod"], "prod") → true |
| distinct(list) |
Returns a list with duplicates removed |
distinct(["a","b","a"]) → ["a","b"] |
| flatten(list) |
Flattens a nested list into a single list |
flatten([[1,2],[3]]) → [1,2,3] |
| concat(lists...) |
Combines multiple lists into one |
concat([1,2],[3,4]) → [1,2,3,4] |
| merge(maps...) |
Merges multiple maps, later keys win |
merge({a=1},{a=2,b=3}) → {a=2,b=3} |
| keys(map) |
Returns a sorted list of map keys |
keys({b=2,a=1}) → ["a","b"] |
| values(map) |
Returns a list of map values |
values({a=1,b=2}) → [1,2] |
| lookup(map, key, default) |
Looks up a key with a default fallback |
lookup({a=1}, "b", 0) → 0 |
| slice(list, start, end) |
Returns a subset of a list |
slice([1,2,3,4], 1, 3) → [2,3] |
| sort(list) |
Sorts a list of strings alphabetically |
sort(["c","a","b"]) → ["a","b","c"] |
| reverse(list) |
Reverses the order of a list |
reverse([1,2,3]) → [3,2,1] |
| toset(list) |
Converts a list to a set (removes duplicates) |
toset(["a","a","b"]) → set("a","b") |
| tolist(set) |
Converts a set to a list |
tolist(toset([1,1,2])) → [1,2] |
| tomap(object) |
Converts an object to a map |
tomap({a=1,b=2}) |
| zipmap(keys, values) |
Creates a map from separate key and value lists |
zipmap(["a","b"],[1,2]) → {a=1,b=2} |
Practical Collection Example: Merging Environment Tags
A very common pattern is merging a base set of tags with environment-specific ones:
Date and Time Functions
Terraform includes a small set of functions for working with timestamps — useful for generating unique resource names, setting expiry values, or tagging resources with creation dates.
| Function |
What It Does |
Example |
| timestamp() |
Returns the current UTC timestamp as an RFC 3339 string |
timestamp() → "2026-05-01T09:00:00Z" |
| timeadd(timestamp, duration) |
Adds a duration to a timestamp |
timeadd("2026-01-01T00:00:00Z", "24h") |
| timecmp(ts1, ts2) |
Compares two timestamps: returns -1, 0, or 1 |
timecmp(t1, t2) |
| formatdate(format, timestamp) |
Formats a timestamp into a readable string |
formatdate("YYYY-MM-DD", timestamp()) |
| plantimestamp() |
Returns a constant timestamp fixed at plan time (Terraform 1.5+) |
plantimestamp() |
Practical Date Example: Tagging Resources with a Creation Date
Encoding Functions
Encoding functions let you convert data between different formats — essential when you need to pass structured data as strings, or work with base64-encoded secrets and certificates.
| Function |
What It Does |
Example |
| base64encode(string) |
Encodes a string as base64 |
base64encode("hello") → "aGVsbG8=" |
| base64decode(string) |
Decodes a base64 string |
base64decode("aGVsbG8=") → "hello" |
| jsonencode(value) |
Converts a value to a JSON string |
jsonencode({a=1}) → "{\"a\":1}" |
| jsondecode(string) |
Parses a JSON string into a Terraform value |
jsondecode("{\"a\":1}") → {a=1} |
| yamlencode(value) |
Converts a value to a YAML string |
yamlencode({key = "value"}) |
| yamldecode(string) |
Parses a YAML string into a Terraform value |
yamldecode(file("config.yaml")) |
| urlencode(string) |
Encodes a string for use in a URL |
urlencode("hello world") → "hello+world" |
| textencodebase64(string, encoding) |
Encodes a string to base64 using a specific charset |
textencodebase64(str, "UTF-16LE") |
| base64gzip(string) |
Compresses and encodes a string as base64 |
base64gzip(large_script) |
Practical Encoding Example: Passing a JSON Policy to AWS IAM
Filesystem Functions
Filesystem functions let you read files from your local disk into your Terraform configuration. This is useful for loading scripts, certificates, policies, and other external content.
| Function |
What It Does |
Example |
| file(path) |
Reads a file and returns its content as a string |
file("scripts/init.sh") |
| filebase64(path) |
Reads a file and returns its content as base64 |
filebase64("certs/ca.pem") |
| fileexists(path) |
Returns true if the file exists at the given path |
fileexists("override.tf") |
| fileset(path, pattern) |
Returns a set of file paths matching a glob pattern |
fileset("templates/", "*.json") |
| templatefile(path, vars) |
Renders a template file with variable substitutions |
templatefile("user_data.tpl", {env=var.env}) |
| abspath(path) |
Converts a relative path to an absolute path |
abspath("./modules") |
| dirname(path) |
Returns the directory part of a path |
dirname("/etc/nginx/nginx.conf") → "/etc/nginx" |
| basename(path) |
Returns the filename part of a path |
basename("/etc/nginx/nginx.conf") → "nginx.conf" |
| pathexpand(path) |
Expands ~ to the user home directory |
pathexpand("~/.ssh/id_rsa") |
Practical Filesystem Example: Loading User Data from a Template
Type Conversion Functions
Terraform is a strongly typed language. Sometimes you need to convert a value from one type to another — for example, converting a number to a string so it can be used in a resource name, or converting a list to a set to remove duplicates.
| Function |
What It Does |
Example |
| tostring(value) |
Converts a value to a string |
tostring(42) → "42" |
| tonumber(value) |
Converts a value to a number |
tonumber("42") → 42 |
| tobool(value) |
Converts a value to a boolean |
tobool("true") → true |
| tolist(value) |
Converts a set or tuple to a list |
tolist(toset([1,2,3])) |
| toset(value) |
Converts a list or tuple to a set |
toset(["a","b","a"]) → set("a","b") |
| tomap(value) |
Converts an object to a map |
tomap({a=1, b=2}) |
| can(expression) |
Returns true if an expression does not produce an error |
can(var.config.key) |
| try(expressions...) |
Returns the first expression that does not error |
try(var.opt, "default") |
| type(value) |
Returns the type of a value as a string (for debugging) |
type(var.input) |
Practical Type Conversion Example: Safe Optional Variable Lookup
The try function is especially useful when working with optional or nested variables that might not always be set:
Hash and Crypto Functions
Hash functions generate a fixed-length fingerprint of a value. They are often used to generate unique identifiers, detect changes, or create deterministic resource names based on content.
| Function |
What It Does |
Example |
| md5(string) |
Returns the MD5 hash of a string |
md5("hello") → "5d41402..." |
| sha1(string) |
Returns the SHA-1 hash of a string |
sha1("hello") |
| sha256(string) |
Returns the SHA-256 hash of a string |
sha256("hello") |
| sha512(string) |
Returns the SHA-512 hash of a string |
sha512("hello") |
| bcrypt(string, cost?) |
Returns a bcrypt hash of a string |
bcrypt(var.password, 10) |
| uuid() |
Returns a randomly generated UUID string |
uuid() → "da3df..." |
| uuidv5(namespace, name) |
Returns a deterministic UUID v5 |
uuidv5("dns", "example.com") |
| filemd5(path) |
Returns the MD5 hash of a file |
filemd5("app.zip") |
| filesha256(path) |
Returns the SHA-256 hash of a file |
filesha256("lambda.zip") |
Practical Hash Example: Triggering Lambda Redeployment on Code Change
A very common pattern is using filesha256 to force a Lambda function to redeploy only when its deployment package actually changes:
IP Network Functions
IP network functions help you work with CIDR blocks — splitting them, calculating subnet addresses, and checking whether an IP falls within a range. These are invaluable for networking configurations.
| Function |
What It Does |
Example |
| cidrhost(prefix, hostnum) |
Returns the IP address of a specific host in a CIDR block |
cidrhost("10.0.0.0/24", 5) → "10.0.0.5" |
| cidrnetmask(prefix) |
Returns the subnet mask of a CIDR block |
cidrnetmask("10.0.0.0/24") → "255.255.255.0" |
| cidrsubnet(prefix, newbits, netnum) |
Calculates a subnet address within a CIDR block |
cidrsubnet("10.0.0.0/16", 8, 1) → "10.0.1.0/24" |
| cidrsubnets(prefix, newbits...) |
Returns multiple consecutive subnets from a CIDR block |
cidrsubnets("10.0.0.0/16", 4, 4, 4) |
| cidrcontains(cidr, ip) |
Returns true if an IP is within a CIDR range |
cidrcontains("10.0.0.0/24", "10.0.0.50") → true |
Practical IP Example: Generating Subnets Dynamically for a VPC
How env zero Helps You Get More From Terraform Functions
Terraform functions are powerful on their own — but they become even more valuable when your entire team is using them consistently, inside approved module patterns, with policy guardrails that catch misuse before it reaches production.
env zero gives platform and cloud teams the layer of governance that Terraform does not ship with:
• Standardised modules — reusable patterns that already use the right functions for naming, tagging, and networking, so every team starts from a solid baseline.
• Policy enforcement — automated checks that validate resource naming conventions, required tags, and CIDR configurations before a terraform apply is allowed to run.
• Drift detection — if someone bypasses Terraform and makes a manual change, env zero flags the drift immediately so your functions-generated names and tags stay the source of truth.
• Cost visibility — tags generated using merge, format, and lower feed directly into env zero's cost attribution dashboards, so you can see spending by team, project, and environment without any extra work.
Whether you are just starting with Terraform functions or building a mature, multi-team IaC platform, env zero is designed to help you scale confidently.
Frequently Asked Questions
Can I define my own functions in Terraform?
No — Terraform does not currently support user-defined functions. You work with the built-in library. However, you can achieve similar reuse through locals (for computed values), modules (for reusable patterns), and expressions. The Terraform team has discussed custom functions as a future feature, and OpenTofu has begun exploring this capability.
Where can I use functions in Terraform?
Functions can be used anywhere Terraform evaluates an expression — inside resource arguments, variable defaults, locals, outputs, and data source arguments. They cannot be used in the terraform block itself (for backend configuration), as that block is evaluated before variables are available.
What is the difference between locals and functions?
Functions are built-in operations that transform a value — like upper() converting a string to uppercase. Locals are named values you define yourself, which can call functions. You typically combine them: use a function inside a local to compute a reusable value once, then reference the local throughout your configuration.
Are Terraform functions the same in OpenTofu?
Yes — OpenTofu is a fork of Terraform and supports the same built-in function library. OpenTofu 1.7 and later also added provider-defined functions, which allow Terraform providers to ship their own custom functions. This is a capability that does not yet exist in Terraform itself.
How do I debug a Terraform function call?
The easiest way is to use a terraform console session. Run terraform console in your working directory and type function calls interactively to see their output immediately. It is the fastest way to test expressions without running a full plan.