Design Variables for Composable Terraform Modules
Learn patterns for designing Terraform module interfaces with required vs optional variables, sensible defaults, and object-typed inputs.
Detailed Explanation
Module Composition Variable Patterns
Well-designed module variables make the difference between a module that's easy to use and one that's a maintenance burden. Follow these patterns for clean, composable module interfaces.
Pattern 1: Required vs. Optional
# Required — no default, caller must provide
variable "project_name" {
type = string
description = "Name of the project (required)"
}
# Optional — has a sensible default
variable "log_retention_days" {
type = number
description = "CloudWatch log retention in days"
default = 14
}
Pattern 2: Feature Toggles
variable "enable_monitoring" {
type = bool
description = "Enable CloudWatch monitoring and alarms"
default = true
}
variable "enable_backup" {
type = bool
description = "Enable automated backups"
default = false
}
Pattern 3: Configuration Objects with Optional Fields
variable "monitoring_config" {
type = object({
enabled = bool
alarm_email = optional(string)
retention_days = optional(number, 30)
detail_level = optional(string, "basic")
})
description = "Monitoring configuration"
default = {
enabled = true
}
}
The optional(type, default) syntax (Terraform 1.3+) lets callers omit fields while providing defaults.
Pattern 4: Map of Objects for Multiple Instances
variable "databases" {
type = map(object({
engine = string
instance_class = string
storage_gb = number
multi_az = bool
}))
description = "Map of database configurations keyed by logical name"
default = {}
}
Usage: databases = { main = { engine = "postgres", ... }, analytics = { engine = "mysql", ... } }
Design Principles
- Minimize required variables: Every required variable is friction for the caller
- Group related settings: Use objects instead of 10 separate variables
- Validate early: Catch mistakes at plan time, not apply time
- Document defaults: Make it clear what happens when a variable isn't set
- Use
optional(): Reduce boilerplate for complex objects
Use Case
Teams building shared Terraform module libraries where clean, well-documented variable interfaces reduce friction and errors for module consumers.
Try It — Terraform Variable Generator
Related Topics
Define Common Tags as a map(string) Variable
Common Patterns
Define Environment Name Variable with Allowed Values
Common Patterns
Define S3 Bucket Configuration as an Object Variable
Resource Configuration
Define Security Group Rules as Object Variables
Networking
Use Boolean Variables for Conditional Resource Creation
Advanced Patterns