Module for_each methodology and footprint

When writing modules with Terraform I generally find grouping tightly coupled resources into a single module. For instance, vnets, subnets, nsgs, firewalls, (core network) are some examples of some tightly coupled dependencies. In addition I leverage lists of primitive objects for each resource so they retain their logical identity. This allows me to refrence any dependency directly using their unique properties. This limits the amount of modules that one would need using contrary methods, like modules operating on single resources and the dependency references being passed directly to the module from a module.

What this has lead to though is my module definitions do not utilize the for_each Metadata property, instead a list of objects is passed to the module as a variable once, and for_each is utilized internally with the resources in the module. This works well for me and I have no plans for changing this current methodology, especially with primitive object type support in variables declarations with the experimental optional type. However my question is, is there a point where lists of primitive objects may become too big of a data structure footprint. Are there limitations of passing these large lists of primitives vs grainular module per resource utilizing for_each? My understanding of how terraform compiles in these different scenarios leaves a bit of a “black box”, so to speak, for my understanding.

Hi @DataDecay,

I think you are asking about the design tradeoff of either having variables in your module that accept collections describing multiple objects for the single module to create vs. having the module deal only in singular objects and have the caller use for_each for the module as a whole.

This decision should be motivated purely by what the module represents, which is ultimately up to you as the module author. For example, if you have a module representing “a virtual network” which is defined as a virtual network with one or more subnets then it would likely make sense for that module to accept some sort of collection representing the multiple subnets to create, but only a singular definition of settings relating to the the network as a whole, such as its base CIDR block.

But then a user of that module might want to declare multiple networks, each with its own subnets. In that case they might choose to use for_each with your whole module to systematically choose base CIDR blocks and subnet configurations. Your module represents one network, and their multi-instance module blocks represents many networks.

However, you might instead prefer to write a module that represents “the entire network topology”, which encapsulates even the possibility of multiple networks. Terraform doesn’t really care which of these strategies you choose: ultimately it’s more about finding an appropriate model of the intended architecture that future humans will be able to successfully understand and maintain.

I hope that answers the question!