The Terraform Module Layout I Reuse on Every AWS Project
Most Terraform pain is not Terraform. It is layout. A project with no convention becomes a project where every change is archaeology. So I bring the same skeleton to every engagement and tune it rather than reinvent it.
The shape
textinfra/ modules/ network/ compute/ data/ envs/ dev/ main.tf backend.tf prod/ main.tf backend.tf
Modules describe how a thing is built. Environments describe which things exist and with what values. The two never blur. A module never knows whether it is in dev or prod, and an environment never contains resource logic, only composition.
State is not optional
Remote state in S3 with a DynamoDB lock table is the first thing I set up, before any real resource. Local state on someone's laptop is how two engineers quietly destroy each other's work on a Friday afternoon.
- One state file per environment, never one giant shared file.
- State bucket has versioning on, so a bad apply is recoverable.
- The lock table is created out of band so it never depends on the state it protects.
If you cannot answer who last changed prod and when, you do not have infrastructure as code. You have infrastructure with extra steps.
Why the discipline pays off
When the layout is identical across projects, onboarding is reading, not interrogation. A new engineer opens envs, sees exactly what exists, opens modules, sees exactly how. The structure itself is documentation that cannot drift out of date.