The apply queue disappears when the lock does
Terraform gives a state one lock, so changes queue behind each other. Stategraph locks the resources a change touches, so disjoint changes apply at the same moment and only real overlap waits.
Where the concurrency comes from
The lock covers the change, not the file
Lock scope
Two applies, one state, same moment
Terraform locks the whole state file for every operation. Stategraph locks the resources a change touches, so two changes to different resources apply at the same moment.
Resource-level locking →Illustrative. Same state, same moment. Different resources, so neither waits.
Conflicts
Overlap is settled at commit
Nothing is arbitrated up front. Everyone plans at once, and a real overlap is rejected at commit with the conflicting transaction ID, then re-planned.
Transaction model docs →tx-a and tx-b touch different resources and commit. tx-c touched a resource tx-a changed, so it is rejected and re-planned.
Multi-state transactions
Producer and consumer in one plan
With a state file, you apply the producer first and hope. Stategraph plans the producer and the consumer together, and the consumer reads the producer's pending output.
Cross-state plans →Real output. Same terraform_remote_state HCL.
Atomic apply
Every state commits, or none does
Terraform applies networking, compute, and application states one at a time, in an order you maintain. Stategraph commits every state in one transaction, and if anything fails, nothing applies.
Multi-state transactions →Illustrative. rm2 reads rm1's pending network_id inside the same transaction, so the order is derived, not hand-maintained.
Underneath
PostgreSQL's concurrency model
Reads never block writes
Reads work against a consistent MVCC snapshot, so a reader never blocks a writer and a writer never blocks a reader.
Plans pinned to a revision
Every plan is pinned to the state revision it was computed against, so a long plan does not become worthless because someone else applied first.
One state for the whole team
Contention tracks real overlap, not headcount, so adding engineers does not add queue time.
MVCC plus row-level locks, not a file mutex on a JSON blob. Resource-level locking docs →
Stop letting one lock decide who ships
Keep one coherent state for the whole team and let disjoint changes land together. Bring a state file and see it running against your own infrastructure.