# stategraph/stategraph: Terraform state as a dependency graph instead of a locked file

> Stategraph is an OCaml project with an MPL-2.0 licence that runs Terraform and OpenTofu from pull requests and can store the state as a graph in PostgreSQL rather than a file, so a plan reads only the subgraph a change touches and independent changes apply at the same time. The open source build covers the orchestration half for up to three active users a month, while the database half is an enterprise product.

**stategraph/stategraph** — Terraform without the state file bottleneck

- Repository: https://github.com/stategraph/stategraph
- Website: https://stategraph.com
- Stars: 1,314 · Forks: 84
- Language: OCaml
- License: MPL-2.0
- Published: 2026-10-19 · Updated: 2026-10-19 · Language: en
- Canonical page: https://hysenlabs.com/projects/stategraph-stategraph

## The state file is a lock, and that is the real bottleneck

The project's tagline is Terraform without the state file bottleneck, and the mechanism behind it is stated precisely.

With a state file, every write locks the whole file. Infrastructure as a Database stores each state as a graph of resources and dependencies in PostgreSQL, and locks only the resources a change touches.

That is the whole idea, and it explains the two properties that follow. A plan is scoped, reading only the subgraph your change reaches rather than the whole state. And changes are concurrent, because each plan and apply is a transaction that locks the resources it changes, so changes that do not overlap apply at the same time, while changes that do overlap are rejected at commit.

The rejection behaviour is worth noting, because it is the safety argument. Two pull requests that touch the same resource do not silently interleave, they are refused, and the second one is left to be rebased. A global lock prevents concurrency; a per resource lock prevents interference while allowing the safe cases to proceed in parallel.

The project is written in OCaml, licensed MPL-2.0, and lives at stategraph.com with documentation, a blog and a Slack community.

## Two products that work without each other

Stategraph has two parts, and the README is careful to say that each part works without the other, so you can start with Orchestration against your existing state backend and move the state into the database later.

Stategraph Orchestration plans every pull request on GitHub or GitLab and posts the result as a comment. Policy checks, cost estimates and approvals run in the review, and the apply runs on merge or on a comment. It is open source and self-hostable.

Stategraph Infrastructure as a Database stores each state as a dependency graph in PostgreSQL. A plan reads only the resources your change reaches, changes that touch different resources apply at the same time, and you can query every state with SQL. It works from the CLI with any CI system, and no VCS provider is required.

That split is the commercial structure as well as the technical one. The orchestration half is the open source part, and the database half is where the interesting engineering is. The architecture diagram in the README shows the platform as pull requests, the CLI, the API and AI agents connecting to the Stategraph server, with Orchestration running on top of Infrastructure as a Database, and the combination powering policy, remote execution, inventory, cost, security and compliance.

So the platform can be bought as a whole, and the pieces are separable for the team that only needs one of them.

## Orchestration: the plan is a review comment

The orchestration model puts the plan where the code review already happens.

A plan is run on every pull request and posted as a comment, and the apply runs on a `stategraph apply` comment or on merge. Approvals are routed by CODEOWNERS, which means the existing ownership rules in your repository decide who signs off on an infrastructure change, with no new permission model to design.

The policy layer runs before an apply, with OPA and Rego, Conftest and Checkov all supported. Those are the three tools a policy team is most likely to already have, which is a deliberate choice to meet people where they are rather than asking them to learn a policy language.

Cost estimates appear in the pull request, with thresholds that require another approval. That is a nice detail, because a cost estimate that is merely informational gets ignored, while one that changes who has to approve changes behaviour.

Two more capabilities round it out. Drift detection runs on a schedule, so the estate is checked even when nobody is pushing a pull request. And there is tag-based configuration for ten workspaces or ten thousand, in a monorepo or across repositories, which is the mechanism that makes a single orchestrator usable at either end of that range.

The tools it drives are Terraform, OpenTofu, Terragrunt, CDKTF and Pulumi, and it runs on GitHub and GitLab, configured in a `.stategraph/config.yml` file.

## Querying the estate with SQL

The claim that follows from storing state in a database is that you can ask the estate questions with SQL, and the README shows what that looks like.

```console
$ stategraph query "SELECT type, count(*) FROM resources GROUP BY type"
  aws_instance         20
  aws_security_group   15
  aws_subnet            6
```

The features listed are JOINs, CTEs and blast radius, available from the console, the CLI or the API. Blast radius is the one to pay attention to, because the dependency graph is not only used to decide what to lock, it is also a description of what a change would affect, and being able to ask that as a query rather than by reasoning about the state file is a real capability.

There is a transactional layer on top of that. Every plan and apply is recorded as a transaction with its logs, and a change that reaches several states applies as one transaction with `stategraph tf mtx`. So the history of what was applied, when and with what output is queryable in the same place as the state itself, and a change spanning workspaces is atomic rather than a sequence of partial applies.

## What the open source build actually gives you

The deployment section is where the expectations need setting, and the README is direct about it.

For Orchestration there is a hosted option at app.stategraph.cloud, which connects to GitHub or GitLab, with plan limits on the pricing page. The self-hosted open source route is a clone and a compose file:

```bash
git clone https://github.com/stategraph/stategraph
cd stategraph/docker/terrat

# Run the setup wizard
docker compose up setup
# then open http://localhost:3000
```

And then the limit: the open source build runs Orchestration only, for up to three active users a month per GitHub or GitLab installation. An open-source build of the Stategraph server itself is in development.

For Infrastructure as a Database you need a running Stategraph server first, and there are three ways to get one. The hosted Stategraph Cloud, where the vendor runs the server. The self-hosted Enterprise build, with a license key, on your own PostgreSQL, deployed with Docker Compose, Kubernetes, ECS or Cloud Run. Or a bring your own cloud, where the vendor operates Stategraph inside your AWS, GCP or Azure account.

So the state database, which is the part that removes the lock, is the part that is a commercial product, and the open source part is the part that does not need it. That is a coherent arrangement, since the orchestration half is the one that a self hosting team can plausibly run and the database half is the one that needs a commercial support relationship.

## Installing the CLI and importing a state

Once a server exists, the CLI is installed with a shell script and configured through three environment variables.

```bash
curl -sSL https://get.stategraph.com/install.sh | sh

export STATEGRAPH_API_BASE="https://your-server.example.com"
export STATEGRAPH_API_KEY="<your-api-key>"        # console: Settings -> API Keys
export STATEGRAPH_TENANT_ID="<your-tenant-id>"    # shown in stategraph info

stategraph info                     # confirm the connection
```

The three variables are the address of the server, a key created in the console, and a tenant identifier, and `stategraph info` is the sanity check before you do anything else.

The first operation is importing an existing state, and the command is the familiar one, `terraform state pull`, piped into the import. That is the point at which a team decides whether the move is worth it, since the state that has to move is the same state file that Terraform already knows how to export.

The repository itself is an OCaml project with the usual dune layout, `dune-project`, `dune-workspace` and an `opam/` directory, alongside `code/`, `api_schemas/`, `docker/`, `docs/`, `scripts/`, `config/`, `bin/`, `support/`, `rfds/` for the request for discussion documents, `interviews/` and a vendored `vendor/` tree.

## Where this is the wrong choice

The first wrong case is a team whose bottleneck is not the lock. If your applies are slow because plans are slow, because a provider is slow, or because you have one environment, the state representation is not what is holding you up, and a database backed state store will not help. The README's own framing is that the lock is the problem it solves, so it is worth confirming that it is your problem.

The second is a small team that wants the orchestration half for free. The open source build is limited to three active users a month per installation, which is a generous limit for a team of three and a hard ceiling for everyone else, and the alternative is the hosted product with its plan limits.

The third is a setup where moving the state is riskier than the lock. The database half means changing where the state lives, which is a migration with a rollback plan, and for a small estate a state file with its serialised applies is a problem you can live with.

The fourth is a team that does not want a vendor in the apply path. Orchestration sits between the pull request and the apply, which is exactly where you might want policy checks, and it is also exactly where a new dependency on somebody else's server appears. The self-hosted route exists for that reason and the open source build is limited for that reason.

On the state of the project, the releases are dated builds, with the tags named for their build, 20261012-1006-5e620c0, 20261012-1058-ace8c44 and 20261014-1535-b84a1ee, all within three days of each other, and the last push was on 2026-10-15. The default branch is `main`, the licence is MPL-2.0, and the repository has a `CODEOWNERS` file and a `CONTRIBUTING.md`, alongside a `README.setup.md` that is separate from the main readme, which is where a self hosting setup would look for its steps.

## Conclusion

Adopt Stategraph if the global state lock is what slows your infrastructure delivery down, because the scoped plan and per resource locking model is a genuine structural answer rather than a bigger runner, and the SQL access to state across every workspace is the part that changes what you can ask your estate. Do not adopt the open source build expecting the database half, because that build runs Orchestration only and is limited to three active users a month per GitHub or GitLab installation. Verify first which half you actually need, since the two are sold and licensed separately, that the tool your team uses is in the supported list of Terraform, OpenTofu, Terragrunt, CDKTF and Pulumi, and that the cost of a PostgreSQL backed state store is worth it against the state backend you have now, since the orchestration half works against your existing backend without moving anything.

## FAQ

### What is Stategraph?

It runs Terraform and OpenTofu from pull requests and can store the state as a dependency graph in PostgreSQL instead of a state file, so a plan reads only the resources a change reaches and independent changes apply at the same time. It has two parts, Orchestration and Infrastructure as a Database, and each works without the other.

### How does Stategraph avoid the global state lock?

It stores each state as a graph of resources and dependencies in PostgreSQL and locks only the resources a change touches. Each plan and apply is a transaction that locks what it changes, so non-overlapping changes apply at the same time and overlapping changes are rejected at commit rather than serialised behind a file lock.

### What does Stategraph Orchestration do in a pull request?

It plans every pull request on GitHub or GitLab and posts the result as a comment. The apply runs on a `stategraph apply` comment or on merge, approvals are routed by CODEOWNERS, policy checks with OPA and Rego, Conftest and Checkov run before an apply, and cost estimates appear in the pull request with thresholds that require another approval.

### What is included in the open source build of Stategraph?

The open source build runs Orchestration only, for up to three active users a month per GitHub or GitLab installation, and an open source build of the Stategraph server is in development. The database half is available as Stategraph Cloud, as a self-hosted enterprise build with a license key on your own PostgreSQL, or as a bring your own cloud deployment in your AWS, GCP or Azure account.

### Which infrastructure tools does Stategraph support?

Terraform, OpenTofu, Terragrunt, CDKTF and Pulumi. It runs on GitHub and GitLab and is configured in a `.stategraph/config.yml` file, and it supports tag-based configuration for ten or ten thousand workspaces in a monorepo or across repositories, along with scheduled drift detection.

## Sources

- [License: MPL-2.0](https://github.com/stategraph/stategraph/blob/main/LICENSE)
- [Project website](https://stategraph.com)
- [README](https://github.com/stategraph/stategraph/blob/main/README.md)
- [Releases](https://github.com/stategraph/stategraph/releases)
- [stategraph/stategraph on GitHub](https://github.com/stategraph/stategraph)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/stategraph-stategraph
