Terraform Guide

Learning an existing Terraform codebase: a first week that does not start with main.tf

By the engineer who builds Datadef, from client work on data platforms · Reviewed August 21, 2026

The instinct on day one is to open the largest file and start reading. It is the wrong move, because HCL is easy to read line by line and impossible to weigh: every resource block looks equally important, and in a real platform repository roughly one resource in ten carries the architecture. Read for boundaries first, details later, and get four specific answers from a human because they were never written into the code.

7 min readFor engineers who just joined a team or inherited someone else's platform repo

See it as a diagram

Everything below, as a diagram you can edit. Describe yours and see it in seconds.

142/20003 credits left
Try:

No account needed · Editable canvas, not a picture

Day one: find the things that get applied

A directory of .tf files is a module unit. A unit that no other unit names as a module source is a root module, a thing you can run apply against, and it owns a state. Everything else is a part. That single rule sorts forty directories into a handful of deployment units and a library, and it takes about ten minutes with grep.

Then count the environments. They live in one of three places: a directory per environment with its own backend, a tfvars file per environment, or workspaces selected at apply time. Knowing which convention this repository uses tells you where to look for the differences that matter later.

Read outputs before resources. A module with rich outputs is meant to be composed; a module with none is a leaf that only has side effects. When module B takes module.a.storage_account_id as an input, that is an architectural statement rather than a coincidence, and the set of those statements is the actual shape of the platform.

The four answers no file contains

Which environment is authoritative when they disagree. Most repos have one environment that reflects production reality and one or two that have quietly diverged, and no file says which.

What the repository does not own. Every real platform has resources created before the repo existed, owned by another team, or imported and never finished. Reading the code alone, you will assume the repo is the whole story, and you will be wrong during an incident.

The apply order between stacks, if there is one, and who is allowed to run it. A repository with four backends is four deployment units, and whether they have an order is a fact somebody knows and nobody wrote down.

What broke last time. Ask for the two most recent infrastructure incidents. Ten minutes of that is worth a day of reading, and it tells you which parts of the code are load-bearing in practice rather than in theory.

Write the answers into the README as you get them. A newcomer is the only person on the team who still notices these gaps, and the window closes in about three weeks.

Build the map before you need it

Generate the picture rather than sketching one, for a reason specific to being new: you cannot tell when a diagram is wrong. An experienced engineer looks at a diagram missing a queue and silently corrects for it. Someone in their first week builds their entire mental model on the error and carries it for months.

Connect the repository read-only from GitHub, GitLab, or Azure DevOps and pick the branch that represents reality. Every .tf and .tfvars file is parsed with no init, no state, and no cloud credentials, which matters in week one when your access requests are still pending. What comes back is curated: the Azure platform repository this pipeline was built against declares 123 resources and draws about 36 nodes, with a note counting how much of the remainder is grants, role assignments, and key vault secrets. That ratio is the thing you cannot get from reading files, and it is what stops you from weighting everything equally.

The generated architecture doc ends with a module reference table, one row per module with its source and resource count. Skim it once for proportion, then stop reading and go make a change.

Your first change should be boring on purpose

Pick the least dangerous stack and make a change whose plan you can predict before you run it. The goal is not the change, it is walking the whole loop once: branch, plan, review, apply order, protections. Doing that in week one turns the procedure from folklore into something you have done.

A repository connection is bound to a branch or a tag, so a structural change can be connected on the feature branch as its own project and compared against the one synced from main, zone by zone. That is also the fastest way to discover that a change you thought was local reaches four stacks, which is the mistake newcomers make most often.

The teaching side of this, running the session rather than sitting in it, is covered in explaining infrastructure to a new joiner, and the directory rules in more depth in how to read a Terraform module structure.

Keep a surprises log, dated

One line per thing that was not what you expected, with the date. It becomes the onboarding page for the next hire, and it is the only version of that page that is ever honest. See keeping onboarding docs up to date.

FAQ

How long should it take to understand an unfamiliar Terraform repository?

Structure in about an hour, since the rules are mechanical: root modules are the directories nothing calls as a module source, and environments live in directories, tfvars files, or workspaces. Judgment about which parts are load-bearing takes weeks and comes from making changes, not from reading.

What should I read first in a Terraform codebase?

Not main.tf. Start with the list of root modules and backends, then the environment layout, then the outputs of each module, because outputs define what a module is meant to be composed with. Resource blocks come last, when you already know which module you are in and why it exists.

How do I find out which environment is production?

Ask. Directory and variable names are conventions, not guarantees, and most repositories have at least one environment that has drifted from its label. This is one of the few facts about a platform that is genuinely not in the code.

Can I get an architecture diagram before my cloud access is granted?

Yes. The analysis needs read access to the repository and nothing else. It parses the .tf and .tfvars files with no terraform init, no state file, and no cloud credentials, so it works on day one while other access requests are still in flight.

The repository has no documentation at all. Where do I start?

Generate the derivable layers and write only what cannot be derived. The stack list, the module reference table, and the architecture doc come from the source. What you have to write is intent, the unmanaged resources list, and which environment is authoritative.