We were early and enthusiastic adopters of infrastructure as code, and three years of maintaining that code across client engagements has changed a few of our opinions.
The state file is the real system, and it deserves the same care as production data — locked, backed up, and never edited by hand under pressure. Modules should be boring and specific rather than clever and generic; we've inherited too many "flexible" modules that took longer to understand than to just write plainly. And drift detection needs to actually run on a schedule, not just exist as a command someone could type.
The biggest shift: we now treat the infra codebase with the same review standards as application code, including tests for the things that are testable. It felt like overhead at first. It's paid for itself every time it's caught a change that would have taken down something in production.