USD ($)
$
United States Dollar
Euro Member Countries
India Rupee
د.إ
United Arab Emirates dirham
ر.س
Saudi Arabia Riyal

IaC Best Practices

Lesson 20/50 | Study Time: 35 Min

Knowing how to write IaC is one thing. Writing it well is another. As your infrastructure grows, poorly structured IaC becomes just as painful to maintain as poorly written application code. 

Modularity

The single most important structural practice in IaC is breaking your infrastructure into small, focused, reusable modules rather than writing everything in one large file.

A monolithic IaC file that defines your entire infrastructure — networking, compute, databases, security — in one place is hard to read, hard to test, and dangerous to change. One mistake can affect everything.


The right approach is to separate your infrastructure by concern:

Each module handles one responsibility. The environment folders reference those modules and pass in environment-specific values — different instance sizes, different database configurations, different scaling settings.


Benefits of modular IaC:


1. A change to the database module only affects the database — not networking or compute.

2. The same VPC module can be reused across dev, staging, and production without rewriting it.

3. New team members can understand one module at a time rather than one enormous file.

4. Modules can be tested independently before being used in production.


Versioning

Version Control Your IaC Code: All IaC files must live in a Git repository — not on someone's laptop, not on a shared drive. Every change goes through a pull request, gets reviewed, and is merged with a clear commit message. This gives you a full history of every infrastructure change ever made.


Pin Module and Provider Versions: When you use a Terraform module from the public registry or reference a CloudFormation resource type, always pin to a specific version. If you do not, an upstream update can silently change your infrastructure the next time you run a deployment.


In Terraform, always specify the version for providers and modules:


This tells Terraform to use version 5.x but never automatically jump to version 6.x, which may have breaking changes.

Tag Your Infrastructure Releases: Just as you tag application releases in Git, tag your infrastructure releases too. This makes it easy to identify exactly which version of your IaC was deployed at any point in time — critical for debugging and rollback.

Drift Detection

Drift happens when someone manually changes a resource — through the AWS Console or CLI — that was originally created by IaC. The result is a gap between what your code says the infrastructure should look like and what it actually looks like in AWS.


Drift is dangerous because:


1. Your IaC no longer reflects reality.

2. The next time you run a deployment, the unexpected difference can cause errors or overwrite the manual change.

3. You lose the audit trail — there is no record in Git of what changed or why.

How to Detect Drift

CloudFormation has a built-in drift detection feature. Run it against any stack and it reports which resources have been modified outside of CloudFormation and exactly what changed.

Terraform detects drift automatically when you run terraform plan. If the real AWS state no longer matches the state file, the plan will show the difference as a proposed change.

How to Prevent Drift

The best approach to drift is cultural, the team agrees that all infrastructure changes go through IaC, never through the Console. Enforce this through IAM policies that restrict who can manually modify production resources directly.

For extra enforcement, set up automated drift detection on a schedule — run CloudFormation drift detection or terraform plan nightly as part of a pipeline job. If drift is detected, alert the team immediately.

Other Key Best Practices

Drew Collins

Drew Collins

Product Designer
Profile

Class Sessions

1- What is DevOps? Principles, Culture, and Practices 2- The DevOps Lifecycle 3- Introduction to Cloud Computing 4- AWS Global Infrastructure 5- Core AWS Services Overview 6- Git Fundamentals 7- Branching Strategies 8- Pull Requests and Code Review Best Practices 9- Integrating Git with AWS CodeCommit and GitHub 10- Managing Secrets and Sensitive Files in Repositories 11- What is CI/CD? 12- Building Pipelines with AWS CodePipeline and CodeBuild 13- Automated Testing in CI 14- Deployment Strategies 15- Using GitHub Actions and Jenkins on AWS 16- Why Infrastructure as Code (IaC)? 17- AWS CloudFormation 18- Terraform on AWS 19- AWS Cloud Development Kit (CDK) 20- IaC Best Practices 21- Docker Fundamentals 22- Amazon ECR 23- Deploying Containers with Amazon ECS 24- Kubernetes Basics and Amazon EKS 25- Integrating Containers into CI/CD Pipelines 26- Serverless Computing Concepts and Use Cases 27- Building and Deploying AWS Lambda Functions 28- Event-Driven Automation with Amazon EventBridge 29- Orchestrating Workflows with AWS Step Functions 30- API Gateway Integration for Serverless APIs 31- Introduction to MLOps 32- Training and Deploying Models with Amazon SageMaker 33- Automating ML Pipelines with SageMaker Pipelines 34- Using Amazon CodeWhisperer and AI Tools for Code Automation 35- AI-Powered Testing, Anomaly Detection, and Incident Prediction 36- Observability Fundamentals 37- Amazon CloudWatch 38- Distributed Tracing with AWS X-Ray 39- Centralised Logging with Amazon OpenSearch Service 40- Setting Up Automated Alerts and Incident Response Workflows 41- Shift-Left Security 42- IAM Roles, Policies, and Least-Privilege Access 43- Static Code Analysis and Vulnerability Scanning in CI/CD 44- AWS Security Hub, GuardDuty, and Config for Compliance 45- Secrets Management with AWS Secrets Manager and Parameter Store 46- AWS Well-Architected Framework 47- Auto Scaling and Elastic Load Balancing for Resilience 48- Cost Monitoring with AWS Cost Explorer and Budgets 49- Disaster Recovery Strategies 50- Preparing Your Project for Production