← Back to list

Screaming Architecture on Terraform

Your IaC codebase should be as descriptive as the diagram you draw.

Alejandro Pinola in Level Up Coding · 2024-09-05 19:27 · 0 claps · 2.9 min read
#terraform #screaming-architecture #iac
Open on Medium ↗
Wiki topics: ☁️ · DevOps & Cloud 🏛️ · Architecture

Screaming Architecture on Terraform

Your IaC codebase should be as descriptive as the diagram you draw.

Some time ago I read about Screaming Architecture, a concept initially proposed by Robert C. Martin. In this article, we’ll explore how to implement this concept to describe infrastructure using Terraform.

Table of Contents

· The Problem · What can we do?Example · Simplify onboarding new developers · Do’s and Don’ts · Conclusion

The Problem

The Screaming Architecture idea says when you look at the top-level directory of your application, it should scream what it does like Health Care System, Accounting System, instead of ASP.NET, Angular, or Spring.

I liked the concept and after working on several infrastructure projects using Terraform on most of them, I wondered why not to apply this concept to describe the infrastructure.

In General, I found everyone chooses to create a file or module that describes which cloud resource it creates, rather than its functionality in the infrastructure.

I found a lot of Terraform modules wrapping basic cloud resources, where they only pass a lot of parameters where in the majority of cases they are not used or customized. (YAGNI principle not applied).

Terraform modules are often used to resolve mandatory relations between resources, like creating a Load Balancer in GCP, where you need the Url Map, the Health Checks and Backend configuration resources to establish an E2E solution. And that’s ok, but still, it doesn’t scream the infrastructure’s purpose.

Additionally, infrastructure code is often tightly coupled to the target cloud, even in its naming conventions. For example, you might find a file named storage_account.tf for Azure or s3.tf for AWS. These names don't communicate the purpose of the resources, only the cloud-specific services being used.

What can we do?

We should approach writing our infrastructure code as if we were designing an architectural diagram for a presentation.

Continue using Terraform modules, but focus on encapsulating parts of the infrastructure that can be tested and deployed independently. Parameterize inputs and outputs by carefully considering dependencies and how each module interacts with others.

Example

Let’s say we need to deploy a VM inside a subnet, with a static IP that other services require. In this case:

  • The subnet should be an input to the VM module.
  • The static IP should be created within the VM module and provided as an output.

Avoid adding unnecessary flags or parameters, such as an option to create the static IP or not. If your infrastructure requires it, make it part of the module without adding needless complexity.

When it comes to the VM’s hardware, you can define it initially as local variables within the module. If the hardware configuration depends on the environment (e.g., dev, stage, prod), pass an environment variable to adjust the hardware setup accordingly.

This way, when you look at the main.tf or the root directory files, you'll see fewer individual resources and more relationships between modules, which describe complete, meaningful parts of the infrastructure.

Lastly, be mindful of naming conventions. If the VM hosts a service called “metadata analysis,” name the module accordingly, instead of something generic like “linux_vm.”

Simplify onboarding new developers

An advantage of this approach is it simplifies onboarding new team members because it is easy for them to look into the diagram and find the related resources in the Terraform code base. It is easier to understand and find dependencies.

Moreover, infrastructure changes are easy to understand, because they remain scoped to a module.

Do’s and Don’ts

  1. Don’t over-parameterize. If something changes in your infrastructure, change it, but don’t think something will change beforehand.
  2. Use variables for things that come from the outside, and locals for things you control.
  3. Don’t wrap everything within a module. A storage account is a storage account, you don’t need a module with just one resource to gain control.
  4. Use modules for single resources only if they have a non-standard configuration and are replicated across several solutions, to keep things coherent.
  5. Prefer using IPs, FQDNs, and resource names over full resource references (like passing a complete object) for input and output variables.
  6. Design each module to resolve one part of your infrastructure that can be tested in isolation (considering dependencies should be already available).

Conclusion

Your IaC design should help readers understand the main parts of your infrastructure at a glance, decoupling it from the specific cloud where it is deployed. Name resources according to what they do, not based on the hardware or what they are. Working with modules oriented to your business case should simplify your understanding of how everything connects.


메타데이터
post_id
764ded5ffad8
slug
screaming-architecture-on-terraform-764ded5ffad8
url
https://levelup.gitconnected.com/screaming-architecture-on-terraform-764ded5ffad8
canonical_url
https://levelup.gitconnected.com/screaming-architecture-on-terraform-764ded5ffad8
author_url
https://medium.com/@alepinola
status
ok
fetched_at
2026-07-09 09:18:05