What Is New in Terraform 0.12
Terraform 0.12 is a foundational release that introduces major new language features and a more robust foundation for future development. This table summarizes the key changes.
| Category | Key Changes |
|---|---|
| New Language Features | First-class expressions, generalized type system, conditional expressions, `for` expressions, `for_each` and dynamic blocks |
| Improvements | Improved interpolation, template syntax, plugin installation, and error messages |
| Backwards Incompatibilities | Required syntax changes for lists and maps, new keyword conflicts |
How did Terraform 0.12 change the core language?
The core language received its most significant upgrade, moving from a basic configuration format to a more expressive programming language. This shift enables you to write more dynamic and reusable infrastructure code.
A major change is the introduction of first-class expressions. You no longer need to wrap expressions in interpolation syntax ${...} in most places. This makes the code cleaner and less cluttered. For example, instance_type = var.type now works directly.
The new generalized type system is a big deal. It supports rich data structures and allows for stricter validation, catching type errors at plan time instead of apply time. In practice, this means fewer surprises when you run terraform apply.
What new looping and iteration features were added?
Terraform 0.12 solved the long-standing problem of dynamic resource creation with two powerful new constructs: for_each and for expressions. These features finally provide a clean way to create multiple similar resources or transform collections.
Using for_each on a resource or module allows you to create multiple instances based on a map or set of strings. This is often more flexible than the old count parameter because each instance is tracked by a key, making your state management more stable when adding or removing items.
The for expression lets you transform lists and maps, similar to functionality in other programming languages. You can use it to filter and modify elements within a complex data structure, which is incredibly useful for generating dynamic configuration blocks.
How are conditional expressions different now?
Conditional logic became vastly more powerful with the introduction of the ternary operator. The new syntax condition ? true_val : false_val allows you to choose between two values directly within an expression.
This is a huge improvement over the previous method of using complicated template interpolation tricks with the join and element functions to simulate conditionals. Your code becomes much more readable and intentional.
What are the main upgrade challenges to watch for?
The most common upgrade hurdle involves the new syntax for lists and maps. The legacy syntax using the hashidem.com/hil interpreter is no longer supported. You must update all list and map assignments to use the proper bracket syntax.
You'll also need to watch for new keywords. Words like for, in, and end are now reserved and can no longer be used as identifier names. If your existing code uses these as variable names, you'll get an error and need to rename them.
The terraform 0.12upgrade tool can automate many of these syntax fixes. It's the first place you should run when updating your modules, but always review its changes carefully as it's not perfect for every scenario.
FAQ
Do I have to rewrite all my Terraform 0.11 code for 0.12?
Not entirely, but a significant update is required. The terraform 0.12upgrade tool can handle many syntax changes automatically, such as fixing list and map declarations. However, you must manually review for new keyword conflicts and test the new logic thoroughly.
Is the old interpolation syntax ${...} completely gone?
No, but its use is now greatly reduced. You only need it for embedding expressions within string literals. In most other contexts, like arguments, you can now reference variables and functions directly without the wrapping syntax.
When should I use for_each instead of count?
Use for_each when you need to create resources from a map or a set of strings, especially when the items in the collection may change. It manages state by a unique key, which prevents unnecessary destruction and recreation of resources when the list order changes, a common pain point with count.
Can I use the new for expressions to create resources?
No, and this is a key distinction. The for expression is for transforming and filtering data within expressions (e.g., to generate a list for a input variable). To create multiple resources, you must use the for_each or count meta-argument on the resource or module block itself.
Will my providers and modules break when I upgrade?
Providers that worked with 0.11 should generally work with 0.12, as the provider protocol did not change. However, modules will need to be updated to the new 0.12 syntax. You cannot use a module written for 0.11 in a 0.12 configuration without updating it first.