TrademarkTrademark
Features
Documentation

Top 5 Best Practices for Terraform

5 tips to make you a better Terraform developer
Brendan ThompsonMarch 31, 2023
Top 5 Best Practices for Terraform
Key takeaways
  • Keep Terraform code simple and avoid premature abstraction; a rule of thumb is not to abstract something unless it will be repeated at least five times.
  • Prefer for_each over count because it offers more functionality and control, including conditional and zero-instance provisioning.
  • Build pattern-based modules around repeated organizational patterns such as a database, backend server, and front-end server.
  • Treat locals as a place for global variables or computed properties rather than as a static configuration store.
  • Comment complexity such as intricate for expressions or computed properties so the reasoning is clear to you and others later.

What are the five best practices I always come back to when I write my own Terraform code, or when I help engineers and organizations write theirs? Most of them are common sense. Here they are.

  1. Keep it simple.
  2. Use for_each over count.
  3. Pattern based modules.
  4. Don't use locals as a configuration store.
  5. Comment complexity

Why Should You Keep Terraform Code Simple?

A lot of times in my career, and not just with Terraform, I've seen folks overcomplicate their solution before they need to. I've done it myself. One common mistake is too much abstraction, like creating a module that just wraps an existing Terraform resource. Now you've got a layer on top of that resource that adds little to no value. My rule of thumb: if the thing isn't going to be repeated at least five times, I'm probably not going to abstract it. That's a very personal number, but it gives you a decent starting mark.

When you're writing Terraform, think to yourself: is what I am writing simple, clear, and understandable? If it is, then you're on your way to having some good code for others to consume!

Why Choose for_each Over count?

The count expression is dead, long live for_each. Since I picked up for_each I have never looked back. It gives me far more control over the code. I can provision many instances or none at all, run logic checks on the inputs before anything gets created, and even build things differently depending on those inputs. Try doing that with a count!

How Do You Build Pattern-Based Modules?

When you write Terraform modules, aim to build ones that capture a pattern. Organizations tend to have set patterns for their services. A database, a backend server, a front-end server, that kind of thing. Whatever gets repeated across the organization is a good candidate for a module.

Should You Use locals as a Configuration Store?

Often folks store their entire Terraform input configuration inside a locals block, and to some extent it makes sense. In that scenario you're technically not hard-coding values in the Terraform code itself, but the configuration is still stored alongside it in a very static manner. Instead, change your mindset: think of locals as where your global variables or computed properties live. When you think of them in that way, they actually become a really powerful part of your Terraform code and not a place of confusion.

When Should You Comment Complexity in Your Code?

If you're reading your own code and even for a second think you might forget why, how or what COMMENT it!!! I so often see complex for expressions or lots of explicit dependencies or even complex computed properties in a locals block and it is not always obvious why, a simple comment would make the reason for that complexity crystal clear not only to you but to others alongside and after you! Please take the time to write comments, I would even err on the side of caution and comment more rather than less.

Sign up and get started using these in your free account with Scalr.

About the author
Brendan Thompsonsolutions engineer at Scalr
Brendan Thompson is a solutions engineer at Scalr, specializing in Terraform and cloud infrastructure.