A monolithic stack is sometimes called a “terralith” when used in the context of a Terraform deployment. Monoliths are where most IaC journeys begin. A monolith is the entirety of your infrastructure code in one stack. While monoliths are the least scalable, they do have their benefits.
Monolith Pros:
Lower cognitive load for developers and faster troubleshooting while building
Easier to manage dependencies
More transparent security footprint
Monolith Cons:
Larger blast radius and blocking CI/CD pipeline runs
Tight coupling between resources
Teams encounter dependency issues and can cause issues with other team’s deployments.
Difficulty applying least privilege security principles
Much slower to deploy as it scales
Use When:
Your infrastructure is small and still under heavy development.
Your team is small or still ramping up.
Your team has few security and skill silos.
Ditch when:
Your infrastructure is changing less than it’s growing.
Your modules are mostly static, and changes are less frequent.
You have strict security controls between your teams.
You have highly specialized teams.
As you can see in the diagram, there is only one state for the entire deployment.
Application Stack
An application stack groups the applications with all of their dependencies. This is excellent for a predictable blast radius and full-stack teams that prefer a smaller feedback loop when making modifications.
AGS Pros:
App teams get full control over their application
Blast radius scoped to a single application
Security concerns scoped to application teams
Easier to troubleshoot
AGS Cons:
Teams responsible need to understand full-stack requirements
To run effectively, teams must access the entire stack, including security.
Larger mix of resources means more entropy
Tighter coupling than service group
Duplicated resources
Duplicated teams or teams that have to context switch between applications
Use When:
Your teams need full control over the lifecycle of their application.
Your applications need tight internal coupling.
Your infrastructure does not require multitenancy, such as multiple apps in one Kubernetes cluster.
You have enough teams to manage the applications independently or your teams are capable of context switching between them.
Ditch When:
Multitenancy within services is important due to cost, management, or other.
Security is siloed to a single team.
Your teams are highly specialized and are unable to manage the full stack.
Your teams are unable to context switch to multiple applications.
Service Stack
A service stack splits up the resources needed for an application into its own stack. The applications are all run in their own stack. This is great in that it allows for multitenancy within your services. For example, you can run multiple deployments in the same EKS cluster. This saves cost but introduces possible security issues. In highly sensitive applications, such as healthcare or financial services, this can raise flags when multiple services are running in the same cluster.
Service Stack Pros:
Allows multitenancy and deduplication of resources.
The Infra team is responsible for security. Smaller feedback loop for security modifications.
Service Stack Cons:
The blast radius is large in the service stack.
Security resources are not decoupled.
Use When:
Cost controls and multitenancy are important to your org.
Your infrastructure team is familiar with Terraform and can handle the blast radius.
Your application team does not specialize in infrastructure.
Ditch When:
Your environment is highly regulated.
You need to separate security from infrastructure.
Blast radius management is critical.
Microservice Stack
This is probably an overly extreme example of a Microservice stack pattern, but it is still an example. Every piece of the infrastructure puzzle gets a state and its own configuration. This gives the illusion of control, but you’re stuck with a similar blast radius as the service and application patterns. If a service fails, your application can still fail. You have fewer connected parts that can trigger this failure, but troubleshooting can be a nightmare if there is one. The security of a deployment like this is also difficult due to the number of state files that may need access due to the large number of dependencies between services. Like microservice patterns in traditional programming, it can be great if done carefully, but overall, it should be reserved for specific cases.
Micro Stack Pros:
Teams can be scoped to their expertise
Extremely loose coupling of resources
Blast radius can be small
Security footprint is high due to sharing attributes.
Security resources are isolated.
Micro Stack Cons:
The blast radius is more opaque
Longer feedback loop if separate teams are managing
Dependencies are more challenging to manage
No multitenancy
Use When:
You have highly specialized teams.
You have highly regulated workloads.
The blast radius and security benefits outweigh the cost benefits of multitenancy.
Ditch when:
The complexity adds friction.
You do not have an expert infrastructure team.
Multitenancy and cost controls are a concern.
Rule of Thumb: One Stack per Service and Environment
The best approach for most cases is the service stack pattern. We recommend using one stack per service and environment, whereas a service can comprise multiple applications and backing infrastructure.
Based on the specifics of your project and your team setup, there may be alternatives. We are happy to review your IaC structuring considerations. Feel free to share in our Discord Community . Otherwise, we look forward to see how you decided to structure your stacks .
Soren is the co-founder and Chief Executive Officer at Terramate. Prior to founding Terramate, he consulted companies such as Flink, 1Komma5 and Nothing to design and implement cloud- and internal developer platforms.