Best Practices
Best Practices
March 31, 2023

Top 5 Best Practices for Terraform

Brendan Thompson

What are the five best practices I always consider when writing my own Terraform code or helping engineers and organizations write Terraform. In my opinion they are all pretty common sense but lets go over them!

  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

Keep it Simple

I have found a lot of times in my career - not just with Terraform - that folks tend to overcomplicate their solution prematurely, I have been known to do this myself from time to time. One common mistake I see made with over complication is the excessive use of abstraction, such as creating a module that simply wraps an existing Terraform resource we are now creating a layer on top of that resource that provides little to no value at all. My rule of thumb is if the thing isn't going to be repeated at least five times I am probably not going to abstract it, this is a very personal number but it does give a decent start 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!

for_each > count

The count expression is dead, long live for_each. Since getting the for_each expression I have never looked back, it offers so much more functionality and control over our code. It allows us to provision multiple instances, no instances or perform rather complex logic checks on inputs before provisioning things, it even allows us to provision things in different ways dependent on those inputs. Try doing that with a count!

Pattern Based Modules

When writing Terraform modules it is a good idea to opt for creating ones that create a pattern. Organizations tend to have patterns set out for their services, think a database, backend server, and a front end server it is something likely to be repeated within the organization and thus makes a good fit for becoming a module.

Don't use locals as a configuration store

Often folks store their entire Terraform input configuration inside a locals block, and to some extent is makes sense? In that scenario you're technically not hard-coding values in the Terraform code itself but the configuration is still stored along side it in a very static matter. Instead, change your mindset think of locals as where you 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.

Comment Complexity

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 bother 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.

Note: While this blog references Terraform, everything mentioned in here also applies to OpenTofu. New to OpenTofu? It is a fork of Terraform 1.5.7 as a result of the license change from MPL to BUSL by HashiCorp. OpenTofu is an open-source alternative to Terraform that is governed by the Linux Foundation. All features available in Terraform 1.5.7 or earlier are also available in OpenTofu. Find out the history of OpenTofu here.

Start using the Terraform platform of the future.

A screenshot of the modules page in the Scalr Platform