Best practices · Cloud and DevOps
Terraform Best Practices
Opens with creditsA practical guide to Terraform best practices for people who manage cloud infrastructure as code. It covers structuring and formatting configuration, pinning Terraform, providers and modules, storing state remotely with locking, keeping secrets out of state, writing modules and refactoring them safely, and a review workflow with plans, tests and policy.
What you will learn
6 chapters · about 19 min
1Structure and styleHow to lay out files, name things and format code so every Terraform change is easy to read in a pull request.4 practices · 3 min
2Versions and dependenciesHow to pin Terraform itself, providers and modules so that a plan run next month uses the same code as the one you reviewed today.4 practices · 3 min
- State: remote, locked and splitTerraform state is the map between your code and real resources. These practices keep it shared, safe from concurrent runs, recoverable and small enough to reason about.4 practices · 4 minOpens with credits
- Secrets and credentialsHow to give Terraform the credentials it needs and pass secrets to resources without leaving them in Git, logs, state or plan files.4 practices · 3 minOpens with credits
- Modules and refactoringWhen to write a module, how to repeat resources safely, and how to rename or move resources without Terraform destroying them.4 practices · 3 minOpens with credits
- Workflow, tests and policyHow changes move from a branch to production: plans in review, applying exactly what was reviewed, tests for modules and checks on deployed infrastructure.4 practices · 3 minOpens with credits
About this guide
Terraform best practices exist because infrastructure code fails differently from application code. A bad commit in an app usually means a bug you can roll back. A bad Terraform apply can delete a database, replace a load balancer that customers are hitting, or leak a password into a state file that half the company can read. The tool will do exactly what the configuration and the state say, so most of the craft is making sure both are right before anything is applied.
This guide follows the order you meet these problems. It starts with how to lay out and format configuration so reviews are easy, then how to pin Terraform, provider and module versions so a run next month behaves like a run today. The middle chapters cover state, which is the part that hurts most when it goes wrong: remote backends, locking, encryption and splitting state into safe pieces, then secrets and why marking a value sensitive is not the same as keeping it out of state. The last chapters cover modules and refactoring without destroying resources, and a workflow where every change is planned, reviewed, tested and checked against policy.
Every practice was checked against the current Terraform documentation on developer.hashicorp.com, including the official style guide, the pages on sensitive data, the S3 backend, refactoring with moved blocks, import blocks, the dependency lock file, version constraints and the testing framework. Each one tells you what to do, what to avoid and how to check it, with HCL you can adapt.
The advice applies whether you run Terraform from a laptop, from CI or through HCP Terraform. Where a practice depends on a paid feature, it says so and gives the open alternative.
Common questions
Should I commit .terraform.lock.hcl?
Yes. The Terraform docs recommend committing it so provider version changes go through code review. Run terraform init -upgrade to move to newer allowed versions, and terraform providers lock with each platform your team and CI use so checksums cover all of them.
Does sensitive = true keep secrets out of Terraform state?
No. It only hides values from CLI output and the UI. Terraform still stores them in state and plan files. To keep a secret out of state, use ephemeral values (Terraform 1.10+) and write-only arguments (1.11+) where the provider supports them.
Is DynamoDB still needed for Terraform state locking on S3?
No. The S3 backend supports a native lock file with use_lockfile = true, and the docs mark DynamoDB-based locking as deprecated and due for removal in a future minor version. You can set both while migrating.
How should I separate dev, staging and prod in Terraform?
Give each environment its own state. Without HCP Terraform, use one directory per environment with its own backend and variables, calling shared modules. With HCP Terraform, use a workspace per environment and split large ones further by component.
When should I use count versus for_each?
Use count for identical copies or to turn a resource on and off with count = var.enabled ? 1 : 0. Use for_each when each instance has its own name or settings, because instances are addressed by key and removing one does not shift the others.
How do I rename a Terraform resource without destroying it?
Add a moved block with the old address in from and the new one in to, then plan. The plan should say the resource has moved, with no create or destroy. Keep the block in shared modules so callers on older versions can upgrade safely.
Sources (8)
Checked against these, last on 13 October 2026.
- Style Guide, HashiCorp Terraform docsdeveloper.hashicorp.com/terraform/language/style
- Manage sensitive data in your configuration, HashiCorp Terraform docsdeveloper.hashicorp.com/terraform/language/manage-sensitive-data
- Backend block configuration overview: s3, HashiCorp Terraform docsdeveloper.hashicorp.com/terraform/language/backend/s3
- Dependency Lock File, HashiCorp Terraform docsdeveloper.hashicorp.com/terraform/language/files/dependency-lock
- Version Constraints, HashiCorp Terraform docsdeveloper.hashicorp.com/terraform/language/expressions/version-constraints
- Refactoring modules, HashiCorp Terraform docsdeveloper.hashicorp.com/terraform/language/modules/develop/refactoring
- Import existing resources, HashiCorp Terraform docsdeveloper.hashicorp.com/terraform/language/import
- Tests, HashiCorp Terraform docsdeveloper.hashicorp.com/terraform/language/tests
Related on Sefism
Picked from the other libraries by shared topics.
Roadmaps
See allCheat sheets
See allBest practices
See all- Kubernetes Best PracticesRun workloads on Kubernetes that schedule well, survive restarts and node drains, and stay locked down: resources, probes, PDBs, Pod Security and RBAC.
- CI/CD Best PracticesBuild pipelines that are fast, trustworthy and safe to deploy from: trunk-based flow, fast tests, locked-down workflows, signed artifacts, canaries and DORA metrics.
- Observability Best PracticesKnow when production is hurting users and why: SLOs, golden signals, metric naming and cardinality, structured logs, OpenTelemetry traces and burn-rate alerts.
Checklists
See all- Incident Response ChecklistPrepare for and handle production incidents: on-call, severity levels, declaring, roles, mitigation, security containment, status updates and blameless postmortems.
- Production Readiness ChecklistCheck a service before it takes real traffic: ownership, SLOs, capacity, timeouts and retries, alerts, rollout and rollback, backups, security and on-call.
- Kubernetes Production ChecklistVerify a workload and its cluster before real traffic: requests and limits, probes, PDBs, spread, Pod Security, RBAC, network policies, secrets, images, autoscaling, upgrades and backups.
Project structures
See all- Terraform project structureAn infrastructure repository for a small app on AWS: reusable modules, one folder per environment with its own remote state, pinned providers, tests and security scans, with plan on every pull request and apply from CI. For students who have finished the Terraform tutorials and want to know how a real team lays out the files. The same layout works unchanged with OpenTofu.
- Kubernetes with Helm project structureA Helm chart repository for one app: the chart that
helm creategives you, grown into a tested, versioned package with per-environment values, unit tests, install tests in a kind cluster and releases to an OCI registry. For students who can write a Deployment by hand and want to know how a team organises charts. It is about the repo layout and what each file does, not about cluster design. - Spring Boot project structureA REST API in Java with Spring Boot 4, PostgreSQL, Flyway and Testcontainers, organised by feature the way the Spring docs suggest. It grows from the Initializr scaffold to a service with JWT security, problem-detail errors, MapStruct DTOs, slice and integration tests, CI, containers and observability, and finally Modulith boundaries, contract and load tests. For students who know some Java and want to see how a real service is organised.
Career questions
See all- Do I need Docker and Kubernetes as a junior developer?Docker, yes: learn the basics, because nearly every team uses containers and you will be expected to run the project locally and read a Dockerfile. Kubernetes, mostly no: understand what it does and a few core terms, but deep Kubernetes can wait until your job or a DevOps direction needs it.
- What is platform engineering, and how is it different from DevOps?DevOps is a culture and set of practices: developers and operations sharing responsibility for shipping and running software. Platform engineering is one way to put that into practice at scale: a team builds an internal platform, a paved road of tools and templates, so product teams can ship without becoming infrastructure experts.
- Can I become an SRE or platform engineer straight after graduating?Sometimes, but it is rare, because these roles expect you to have run production systems. The more reliable path is a first job in backend, DevOps or cloud support, where you learn production, then a move into SRE or platform work within a couple of years.
Stuck on something specific?
Writing only gets you so far. If you want an answer to your situation rather than the general case, book a session and we will work through it together. Sessions are free for approved Sefism members, and a few slots open each week.
- 1:1 Mentorship
- Fresh Graduate Mentorship
- Career Guidance
Brand deals, promos and partnerships: tauseeffayyaz@gmail.com