Resource-level locking

Two engineers, one state, zero contention.

Terraform locks the entire state file for every operation. Stategraph locks only the resources your change touches — so disjoint changes run in parallel and conflicts are detected only on real overlap.

Subgraph-scoped locks Disjoint = parallel 409 only on real overlap
Get Started See it in action

The global state lock is the wrong primitive

In Terraform, one engineer touching one resource blocks everyone else on that state — even on completely unrelated resources. The lock is on the file, not on what you're actually changing.

Two applies, same state, same moment

An illustrative scenario: two engineers apply against the same state at the same time. Because their changes touch different resources, Stategraph locks each subgraph independently — neither waits on the other.

dev-a $ engineer a
❯ stategraph apply        # editing aws_instance.web
Locking aws_instance.web…
Apply complete ✓
dev-b $ engineer b
❯ stategraph apply        # editing aws_security_group.app
Locking aws_security_group.app…
Apply complete ✓

Same state, same moment. Different resources → no waiting.

STATEGRAPH Dev A apply aws_instance.web ✓ done Dev B apply aws_security_group.app ✓ done disjoint subgraphs → both run now TERRAFORM Dev A apply (global state lock) Dev B blocked — waiting for lock

A lock that fits the change, not the file

// Terraform
1one global lock per state
2any op blocks all others
3teams split state to cope
4fragmentation + coordination
→ queue up and wait
// Stategraph
1lock only your subgraph
2disjoint changes run in parallel
3overlap → HTTP 409, re-plan & retry
4MVCC reads never block writes
→ one state, whole team

What you get

Subgraph locks

Stategraph locks the exact resources your change touches — not the whole state file. The blast radius of a lock is the blast radius of your change.

Parallel disjoint applies

When two changes touch different resources, they run at the same time. No queue, no waiting your turn behind an unrelated apply.

Conflict only on overlap (409)

You only hit a conflict when two changes genuinely touch the same resource. Stategraph returns an HTTP 409 so you can re-plan and retry.

MVCC snapshots

Reads work against a consistent snapshot, so reading state never blocks a writer and a writer never blocks a reader.

Scales with team size

More engineers on one state doesn't mean more time spent in the lock queue. Contention tracks real overlap, not headcount.

No state splitting needed

Stop carving state into tiny files just to dodge the global lock. Keep one coherent state and run changes in parallel.

This is PostgreSQL's proven concurrency model — MVCC plus row-level locks — not a custom file mutex bolted onto a JSON blob. Transaction model docs →

Stop queueing behind each other

Keep one state for the whole team and let disjoint changes run in parallel. Real overlap is the only thing that ever has to wait.

Get Started Read the Docs

See more in all features  ·  parallel execution →