Infrastructure as code: practices that keep it from becoming the new legacy
Writing infrastructure as code is easy. Keeping it understandable, reviewable and safe to change two years later is the part that takes discipline.By MI Technologies Engineering2 min read
Infrastructure as code (IaC) means describing servers, networks, databases and permissions in files that are versioned, reviewed and applied by tooling. Done well, it makes environments reproducible. Done carelessly, it produces a tangle nobody dares touch.
Why bother
- Repeatability. A new environment is created from code, not memory.
- Review. Changes go through pull requests, so a second person sees a firewall change before it ships.
- History. Version control records who changed what and why.
- Recovery. Rebuilding after a failure becomes a procedure rather than an archaeology exercise.
Habits that keep it healthy
Remote state with locking. Tools such as Terraform track what they manage in a state file. Store it remotely, restrict access, enable locking so two applies cannot collide, and back it up. State can contain sensitive values, so treat it accordingly.
Small, focused modules. Reusable modules for patterns you repeat — a network, a service, a database — reduce duplication. Keep their interfaces small and documented, and version them. Resist modules so generic they need fifty variables.
Separate environments clearly. Development, staging and production should use the same modules with different inputs, ideally in separate state and accounts, so a mistake in one cannot touch another.
Review the plan, not just the code. Always read the planned changes before applying. A tiny code change can plan a destroy-and-recreate of something critical. Post the plan output to the pull request.
Automate apply through a pipeline. Applies should run from CI with controlled credentials, not from individual laptops, so there is one audited path.
Pin versions. Pin provider and module versions and commit the lock file, so upgrades are deliberate.
Handle secrets deliberately
Do not put secrets in code or variables files committed to the repository. Reference a secrets manager, pass values at runtime, and remember that anything written to state may be readable by anyone with state access.
Detect and manage drift
Drift is when real infrastructure differs from the code, usually after a manual change during an incident. Run periodic plans to detect it, decide whether to codify or revert each difference, and make the rule clear: emergency console changes are followed by a code change.
Protect what must not be destroyed
Use lifecycle protections on stateful resources like databases, enable deletion protection where the platform supports it, and restrict who can approve destructive changes. Test risky changes in a non-production copy first.
Test and lint
Run formatting and validation checks, static analysis for security misconfiguration, and policy checks that block things like publicly open storage. These catch problems in review rather than in an incident.
Document the intent
Code shows *what*; comments and README notes should explain *why* — why this network layout, why that instance family, why this exception. Future maintainers will need it.
What to take away
IaC pays off when it is reviewed, applied through one controlled path, split into sensible modules and kept honest by drift checks. Treat it as production software, because it decides what your production is.
MI Technologies Engineering
Software engineering team at Mohansh Innovations Pvt. Ltd.