Infrastructure as Code Migration

Problem:
Manual infrastructure changes led to drift, inconsistency, and slow recovery.
Solution:
Led comprehensive ClickOps→Terraform migration for all AWS assets with full audit trail.
Impact:
MTTR down 40%, infrastructure versioned, repeatability guaranteed.
Overview
Replaced ad-hoc console changes with Terraform-managed infrastructure and reviewable workflows so recovery and scaling follow predictable patterns.
Results & metrics
- 40% reduction in Mean Time To Resolution (MTTR) through codified infrastructure
- 100% of AWS assets migrated from ad-hoc console ClickOps into versioned Terraform code
- Established peer-reviewed plan/apply guardrails with automated state locking
- Zero unplanned production downtime during multi-phase asset migration
Before / after
Infrastructure Safety
Before: Undocumented manual console edits, configuration drift, and tribal knowledge
Disaster Recovery & MTTR
Before: Hours of manual reconstruction following environment incidents
Change Validation
Before: Direct live applies with zero pre-flight impact assessment
What I built
ClickOps to Terraform
Existing AWS resources were imported with terraform import, gradually, not big-bang.
Every change reviewed
Each PR is planned and approved by a human, then applied with a lock and audit trail.
Stack
- Terraform & HCL
- Terraform Cloud, Remote State & Locking
- AWS IAM & CloudFormation Import
- GitHub PR Review Automation
- AWS CLI & Cost Explorer
Decisions
Key trade-offs and design calls that shaped the final delivery.
Terraform over CloudFormation
Why
- Context
- ClickOps was error-prone and unreviewable—console changes had no audit trail
- Decision
- Terraform for version-controlled, reviewable infrastructure—all changes go through PR review
Gradual migration over big-bang
Why
- Context
- Critical services couldn't have downtime during migration
- Decision
- Import existing resources incrementally using terraform import rather than recreating infrastructure
Terraform Cloud over local state
Why
- Context
- Team needed collaboration and state locking for concurrent changes
- Decision
- Remote state with CI/CD integration—prevents state conflicts and enables team-wide visibility
Architecture
The primary system boundaries, runtime pieces, and how the project was structured in production.
- Console ClickOps Assets → terraform import Engine
- Legacy CloudFormation → terraform import Engine
- terraform import Engine → Standardized Modules
- Standardized Modules → Terraform Cloud Remote State
- Standardized Modules → terraform plan PR Check
- terraform plan PR Check → Production AWS Resources (Approved Apply)
- Terraform Cloud Remote State → Production AWS Resources (State Locking)
- Terraform Cloud
State Management
How
Remote state with workspace isolation per environment—state locking prevents concurrent modifications.
- CloudFormation to Terraform
Legacy Migration
How
Imported existing CloudFormation stacks to Terraform using terraform import workflows—gradual, not big-bang.
- Pre-apply checks
Validation
How
terraform plan and custom policy checks required before any apply reaches production.
Mermaid source
Paste into mermaid.live to edit the diagram.
flowchart LR
subgraph Legacy [Unmanaged Legacy AWS]
CO[Console ClickOps Assets]
CF[Legacy CloudFormation]
end
subgraph Engine [Terraform Migration]
IMP[terraform import Engine]
MOD[Standardized Modules]
end
subgraph Governance [State & Review]
TFC[(Terraform Cloud Remote State)]
PLAN[terraform plan PR Check]
end
subgraph Target [Versioned Infrastructure]
AWS[(Production AWS Resources)]
end
CO --> IMP
CF --> IMP
IMP --> MOD
MOD --> TFC
MOD --> PLAN
PLAN -->|Approved Apply| AWS
TFC -.->|State Locking| AWSPipeline
How changes moved from development through validation and deployment.
terraform fmt, validate, and plan on every PR
Infrastructure changes require human approval before production apply
Automated apply after merge with state locking and audit trail
Select a step for its detail
Incidents
Operational failures, rehearsals, or recovery moments that changed how the system was run.
- P3
Generic resource names causing import conflicts
Resolution
Established naming conventions with environment prefixes and resource types before importing
Lesson: Use descriptive, consistent naming schemes—generic names like 'instance-1' cause confusion and import errors
- P2
Terraform import state drift
Resolution
Imported existing CloudFormation resources with terraform import and immediately ran terraform plan to reconcile state
Lesson: Import then immediately plan to catch drift between actual infrastructure and desired state