Broad questions about Terraform and monorepos

I’m currently managing some infrastructure that is organized like this:

  • One terraform config repository per “area”
  • Dozens of repositories for modules that are re-used in these config repositories

The modules are tagged and the config repos pin the tags. So when a module is updated with some fix and the version is bumped, say, from 3.0.0 to 3.0.1, then we need PR’s for all config repositories updating that. If the change requires the recreation of resources, then that might need to be coordinated with other teams that own the applications running in each area.

This works fine but it has some problems:

  • Many PRs for a simple change to some module (PR for module change, PR to update terraform config’s development environment, PR to update the production environment).
  • It’s easy for configuration to be left behind (some module instantiations using v3.0.0 while others using the new v3.0.1)
  • Lots of permissions/webhooks to manage for each Git repository.

So I was thinking about how a single monorepo for the whole infrastructure would look it. Anyone doing this at a large scale with Terraform specifically?

Sometimes the pinning helps because we can update certain parts of the infrastructure and not others, when it’s convenient. But it creates technical debt. For instance, a module that is updated to follow some best practice doesn’t get used across the whole infrastructure and could cause problems later on when breaking changes start to pile up.

What’s your opinion on this? Could anyone share how they are using monorepos with Terraform? And how do you handle applying changes to the whole infrastructure? Are you able to “pin” things even if live config and modules live side by side in the same repo? Multiple branches?

And finally, if you don’t use a monorepo and prefer the arrangement I described above, how do you make it less painful?