Skip to content

Learn · The graph

References make edges

Nobody writes the order. It is a consequence of what refers to what — and depends_on is nearly always a confession that a reference is missing.

Nobody writes the order

A configuration is a set of blocks in whatever sequence somebody typed them. The order things are created in has nothing to do with that: it is derived from the references. A subnet that mentions cloud_vpc.main.id depends on the VPC, so the VPC is built first, and moving the blocks around in the file changes nothing.

That is why the plan document and the apply are ordered differently. The document is alphabetical by address — it is a report. The apply is the graph's order, because it has to be.

The width is the speed

Everything with no dependency between it can run at the same time. A configuration whose graph is one long chain applies one resource at a time however many there are; one that is wide applies in a fraction of the wall clock, with no change to what is built.

So an unnecessary dependency is not a tidiness problem, it is a serialisation. It is the most common reason a large apply takes twenty minutes when it could take three.

Try this
- resource "cloud_bucket" "uploads" { bucket = "orders-uploads-eu-west-1"
+ resource "cloud_bucket" "uploads" { depends_on = [cloud_db_instance.primary] bucket = "orders-uploads-eu-west-1"

Watch: Where the bucket moves to in the walk. It has nothing to do with the database, and now it waits for it.

depends_on is a confession

There is one legitimate use: a dependency that is real and invisible to the configuration — an IAM policy that must exist before something assumes a role, where nothing in the second resource's arguments mentions the first.

Every other use is a reference somebody did not make. Writing depends_on = [cloud_vpc.main] instead of referring to cloud_vpc.main.id gets the ordering and loses everything else: the value is not carried, so nothing downstream is updated when it changes, and a replacement does not cascade through it — because depends_on orders and nothing more.

Before you run it

A bucket has depends_on = [cloud_vpc.main] and nothing else connecting them. The VPC is replaced. What happens to the bucket?

Cycles, and how to break one

Two resources that reference each other have no order, and the planner refuses rather than picking one. The error names the members, which is the useful part — the fix is to find the reference that exists only for ordering and replace it with a depends_on, or to delete it.

The confusing case is a cycle that is not in the configuration at all: create_before_destroy that has not propagated to a dependent produces one, because the ordering constraints have no solution even though nothing refers to itself.

A cycle reported on a configuration with no visible loop is nearly always create_before_destroy failing to propagate. The fix is to add the flag downstream, not to remove it.

The plan

The same service every claim above was made about. Nothing here is graded — load whatever you like, or change nothing and read what the configuration already produces.

No change loaded — the configuration as it stands.
Plan: 0 to add, 0 to change, 0 to destroy.

Nothing in this plan is destroyed.

The walk

cloud_bucket.uploadscloud_db_instance.prima…cloud_iam_policy.bucket…cloud_iam_role.applicat…cloud_vpc.maincloud_security_group.da…cloud_security_group.webcloud_subnet.private["a…cloud_subnet.private["b…cloud_subnet.private["c…cloud_instance.worker[0]cloud_instance.worker[1]cloud_instance.worker[2]cloud_lb.publiccloud_dns_record.api

Left to right is the order. Everything in one column could run at the same time — which is where the parallelism comes from, and why removing a `depends_on` makes an apply faster.

Answer the question above first.Read a plan
Everything you do here stays in this browser.Part of liter8.sh · v0.1.0