Hiding Complexity Behind a Simple Interface
Imagine you are a Platform Engineer at a company with 50 development teams. Each team needs to deploy a "Standard Web Service." Under the hood, that service requires:
- An EC2 instance (or ECS task)
- An Auto Scaling Group with a Launch Template
- An IAM Role with a least-privilege policy
- CloudWatch Alarms for CPU and memory
- A Security Group with company-standard ingress/egress rules
- An Application Load Balancer target group registration
If you hand each team the raw Terraform for all of this, two things happen: (1) they spend a week figuring it out, and (2) half of them disable encryption or skip the CloudWatch alarms because they don't understand why those are there.
The Facade Pattern solves this. You build a module that exposes a tiny, simple interface — just the decisions developers actually need to make — while hiding all the complexity and enforcing all the standards internally.
The Facade in Terraform
The key insight is the deliberate asymmetry between the module's interface (its variables.tf) and its implementation (its main.tf). The interface exposes only what a developer actually needs to decide — a service name, a container image, a replica count, maybe three variables total — while the implementation behind it wires up the IAM role, the security group with company-standard ingress rules, the CloudWatch alarms with pre-agreed thresholds, and everything else, all hardcoded to the platform team's standards. Calling the module from an application repo is just those three values passed in. Encryption is on. Alarms are configured. IAM is least-privilege. The developer didn't have to think about any of it.
The Escape Hatch Problem
A common design question: should the Facade allow overrides? For example, should a developer be able to pass var.encryption_algorithm = "aws:kms" to override the default AES256?
The answer depends on your organization's compliance posture:
- Hard Facade (no overrides): Maximum compliance enforcement. Used in regulated industries (finance, healthcare). The downside is that legitimate edge cases require a platform team ticket.
- Soft Facade (opinionated defaults, optional overrides): More flexible. Use
defaultvalues for all standards, but expose the variable if teams need to override — paired with avalidationblock that constrains the override to a small allowed set (only two specific encryption algorithms, say), so the variable can be overridden but never to something the security team hasn't already blessed.
Key Point: The Facade pattern is a governance tool as much as a usability tool. By controlling the interface, the platform team controls compliance. The discipline is deciding which variables to expose (genuine developer choices) versus which to hardcode (organizational standards). When in doubt, hardcode first and expose only when a real use case demands it.