As your Terraform codebase grows, keeping environments, regions, and IDs in sync with simple variable files becomes difficult to manage. That is usually when patterns using the Terraform zipmap function start showing up in real-world modules, locals, and data transformations.
In this article, we look at when to use zipmap and walk through practical examples.
What is the Terraform zipmap function?
The Terraform zipmap function combines two lists into a single map. The first list provides the keys and the second list provides the values. Terraform pairs each element by index, so the first element of the first list becomes the first key, the first element of the second list becomes the first value, and so on. The first list must be a list of strings used as keys, and the second list can hold any value type.
This function is useful when you need to construct maps dynamically from paired data structures. For example, zipmap(["a", "b"], [1, 2]) results in { a = 1, b = 2 }.
If the lists do not have the same length, Terraform returns an error.
You often use zipmap in modules or dynamic configurations where input variables need to be transformed into a key-value map for use with resources that expect a map input.
Example 1: Creating consistent resource tags
When you want consistent tagging across all cloud resources, zipmap can generate a reusable tag map from two simple lists. This helps avoid repetitive code and makes sure that every resource inherits the same structure.
For instance, if the keys list defines your company’s standard tag names and the values list provides the environment-specific values, zipmap will merge them into a single, easy-to-reference map.
locals {
tag_keys = ["app", "environment", "owner"]
tag_values = ["inventory", "prod", "platform-team"]
common_tags = zipmap(local.tag_keys, local.tag_values)
}Resulting output:
{
app = "inventory"
environment = "prod"
owner = "platform-team"
}Example 2: Producing variable-driven lookup maps
Sometimes you receive configuration data from variables that come in parallel lists. With zipmap, you can convert these lists into a structured map that is easier to index and reuse.
This is especially helpful when modules expect a map input. Terraform evaluates both lists and generates a map that you can reference by key, making your configuration more predictable and easier to understand.
variable "names" {
type = list(string)
}
variable "ports" {
type = list(number)
}
locals {
service_ports = zipmap(var.names, var.ports)
}If the variables contain the following values:
var.names = ["frontend", "backend", "worker"]
var.ports = [80, 8080, 9000]Then the output of the zipmap expression is:
{
frontend = 80
backend = 8080
worker = 9000
}Example 3: Building dynamic settings for modules
Module inputs often require a map of values, but your source data may not start out in a map format.
By using zipmap, you can dynamically build a map that connects each environment name to the correct configuration value, such as a VPC CIDR. This lets you keep environment names and CIDR blocks in separate lists and then combine them into one clear structure for your module.
The final map makes your module calls more readable and reduces duplication across environments.
locals {
environment_names = ["dev", "stage", "prod"]
vpc_cidrs = ["10.0.0.0/16", "10.1.0.0/16", "10.2.0.0/16"]
vpc_config = zipmap(local.environment_names, local.vpc_cidrs)
}Resulting output:
{
dev = "10.0.0.0/16"
stage = "10.1.0.0/16"
prod = "10.2.0.0/16"
}You can then pass local.vpc_config into a VPC module that expects a map of environments to CIDR blocks, instead of managing separate lists inside the module.
How to replace zipmap with a for expression
You can replace zipmap with a for expression when you want more control or when your data is not already in two parallel lists. Instead of pairing two lists by index, you can iterate over one list and look up the corresponding element in the other list, or build a map from a single complex list.
If you normally write:
locals {
keys = ["env", "region", "team"]
values = ["prod", "us-east-1", "platform"]
metadata = zipmap(local.keys, local.values)
}You can replace it with a for expression by iterating over the index of one list and using that index to access both lists:
locals {
keys = ["env", "region", "team"]
values = ["prod", "us-east-1", "platform"]
metadata = {
for i, k in local.keys :
k => local.values[i]
}
}Terraform produces the same result:
{
env = "prod"
region = "us-east-1"
team = "platform"
}This technique is more flexible when you need filtering, transformation, or dynamic conditions. Use this for expression style when you also need to filter or transform values while you build the map.
Key points
zipmap in Terraform is a function that builds a map from two lists: one list of keys and one list of values.
Typical use cases for zipmap include:
- Converting two related lists (like names and IDs) into a single map
- Building variables for modules where maps are easier to work with than parallel lists
- Transforming data from for expressions or tolist() outputs into a map so it is cleaner and more convenient to reference later
Terraform is really powerful, but for an end-to-end secure GitOps approach, most teams use a product that can run and govern their Terraform workflows, like Spacelift. Spacelift takes managing Terraform to the next level by giving you access to a powerful CI/CD workflow and unlocking features such as:
- Policies (based on Open Policy Agent)
- Multi-IaC workflows
- Self-service infrastructure
- Integrations with any third-party tools
If you want to learn more about Spacelift, create a free account today or book a demo with one of our engineers.
Note: New versions of Terraform are placed under the Business Source License (BUSL), but everything created before version 1.5.x remains open source. OpenTofu is an open-source version of Terraform that expands on Terraform’s existing concepts and offerings. It is a viable alternative to HashiCorp’s Terraform, being forked from Terraform version 1.5.6.
Manage Terraform better with Spacelift
Build more complex workflows based on Terraform using policy as code, programmatic configuration, context sharing, drift detection, resource visualization and many more.
