DEV Community

Roberth Strand
Roberth Strand

Posted on • Originally published at robstr.dev on

What a Terraform module should, and should not do

Terraform, like so many other great languages and systems, use modules to help you categories specific pieces of code so that you can reuse it. Ever since I started working with Terraform, I've heard so many variants of what one should use modules for, and I thought I'd share what I have concluded here. Please note, these are just my opinions and even though I work according to them, there is always room for interpretation.

Everything is a module in Terraform, but you shouldn't put everything in a module

Just to clarify, your base Terraform code is considered a module, a root module. This one module does keep track of everything and this is where you execute Terraform. When you call a module from the root module, they are called a child module. What should you move out from the root, and what should you keep?

I think that a healthy root module has a mix of resources and modules. When working with Azure, you don't need to move resource groups creation into a module, they are just a few lines to define. They are also resources that is used by other resources, and should probably be left out of a child module so that their lifecycle is not handled outside of the root module. There are some management patterns that contradict that, but those are edge cases which need to be treated differently.

When do we move resources to a child module

I believe that we should keep resources that are coupled in the same module, as long as it simplifies the structure of the root module, and as long as we keep out resources that have their own lifecycle and dependencies. If we use the resource group as an example of what not to bring into a child module, network interfaces and data disks would live together with the virtual machine as they share the same lifecycle. As always, there are edge cases where this is not true and that's why you need to make sure that your module is flexible enough to handle those. That is a totally different topic altogether.

Virtual machines and their supportive resources, that's one thing. What if you add multiple resources that needs more than one provider? Where should one draw the line? I still think that certain complex modules can exist, but the potential upkeep of complexity should be considered. I would argue that deploying a managed Kubernetes cluster should allow the option to create service accounts and namespaces, but incorporating deployments or the likes? That might bring the complexity to a whole different level. But, if you are in the business of deploying many clusters and they all use Prometheus and Linkerd, maybe having the module deal with that is acceptable. If you have a one cluster that needs these deployments, don't make the module more complex than it has to. Also, application deployment should probably follow one workflow so this might not be the right place to streamline your monitoring solution.

Conclusion

I honestly don't know if this post will be of any help to anyone. We can easily conclude with "it depends", which is always an anti-climatic statement that is very often true. But what I always come back to is this:

Use modules , it's a great way to keep yourself from repetition and help you keep your code clean.

Don't stuff everything into a module , if it doesn't follow the lifecycle or process you're trying to simplify.

Start small and expand , complexity makes it hard to maintain.

Feel free to be opinionated , but allow users to decide if they want to follow your opinion. Sometimes you want to bring your own network interface, sometimes you don't, the option is always nice to have.

AWS Q Developer image

Build your favorite retro game with Amazon Q Developer CLI in the Challenge & win a T-shirt!

Feeling nostalgic? Build Games Challenge is your chance to recreate your favorite retro arcade style game using Amazon Q Developer’s agentic coding experience in the command line interface, Q Developer CLI.

Participate Now

Top comments (0)

DevCycle image

Ship Faster, Stay Flexible.

DevCycle is the first feature flag platform with OpenFeature built-in to every open source SDK, designed to help developers ship faster while avoiding vendor-lock in.

Start shipping

👋 Kindness is contagious

Discover fresh viewpoints in this insightful post, supported by our vibrant DEV Community. Every developer’s experience matters—add your thoughts and help us grow together.

A simple “thank you” can uplift the author and spark new discussions—leave yours below!

On DEV, knowledge-sharing connects us and drives innovation. Found this useful? A quick note of appreciation makes a real impact.

Okay