# petgraph: graph data structures and algorithms for Rust

> petgraph gives Rust programs directed and undirected graphs with arbitrary node and edge data, plus path-finding, minimum spanning trees and DOT export. It is a library choice, not an application, and the trunk branch is mid-transition to a multi-crate layout.

**petgraph/petgraph** — Graph data structure library for Rust.

- Repository: https://github.com/petgraph/petgraph
- Website: https://docs.rs/petgraph/
- Stars: 4,019 · Forks: 467
- Language: Rust
- License: Apache-2.0
- Published: 2026-09-23 · Updated: 2026-09-23 · Language: en
- Canonical page: https://hysenlabs.com/projects/petgraph-petgraph

## The gap petgraph fills between plain vectors and a real graph library

Rust's standard library has no graph type. You get Vec, HashMap and BTreeMap, and from there every adjacency list is hand-rolled: an index type, an edge list, iteration over neighbours, and a pile of index arithmetic that is easy to get subtly wrong. petgraph supplies that layer as a crate. It covers directed and undirected graphs with arbitrary node and edge data, which means the payload attached to a node or an edge is a generic parameter rather than a fixed integer. The README lists four graph types, Graph, StableGraph, GraphMap and MatrixGraph, and states that algorithms for path-finding, minimum spanning trees and graph isomorphisms ship with the crate, with traits exposed so you can implement your own. The audience is Rust developers building compilers, schedulers, dependency resolvers, network models or anything else where the relationships between items matter as much as the items. It is also the graph layer other Rust tooling tends to reach for, so familiarity transfers.

## Four graph types and the index-stability trade-off behind them

The choice of graph type is the first real decision, and the README does not spell out the trade-offs in prose, so the names have to carry the weight. Graph is the default adjacency structure; the example uses UnGraph, the undirected alias. StableGraph exists because removing a node from Graph invalidates indices in ways that can surprise callers, while StableGraph is built so indices stay valid across removals. GraphMap keys nodes by a hashable value instead of an integer index, which suits cases where your identifiers are already strings or structs and you would rather not maintain a mapping table. MatrixGraph stores adjacency as a matrix, which is the right shape for dense graphs and the wrong shape for sparse ones. The crate features section confirms that graphmap, stable_graph and matrix_graph are all enabled by default, so you are not paying a compile-time opt-in to have them available. NodeIndex is the integer handle the index-based types hand back, and the example shows the conversion explicitly, calling g.from_index(2) to turn an integer back into the node key used by the dijkstra result map. That conversion is the seam where index-based and value-based code meet, and it is worth understanding before you pick a type.

## Installing petgraph and running the README example

petgraph is published on crates.io, so a project picks it up through Cargo. The README does not print an install command, but the badge links to the crates.io page and the workspace manifest declares the crate. Add it to your dependencies and let Cargo resolve the released 0.8 line rather than the trunk branch.

```bash
cargo add petgraph
```

The README's own example is the fastest way to confirm the crate is wired up correctly. It builds an undirected graph from an edge list, runs Dijkstra with a uniform cost of 1, computes a minimum spanning tree and prints DOT. Note the imports: the algorithm functions live under petgraph::algo, the DOT writer under petgraph::dot, and the conversion from an element iterator under petgraph::data.

```rust
use petgraph::graph::UnGraph;
use petgraph::algo::{dijkstra, min_spanning_tree};
use petgraph::data::FromElements;
use petgraph::dot::{Dot, Config};
use petgraph::visit::NodeIndexable;

fn main() {
    let g = UnGraph::<i32, ()>::from_edges(&[(0, 1), (1, 2), (2, 3), (0, 3)]);
    let node_map = dijkstra(&g, 0.into(), Some(2.into()), |_| 1);
    assert_eq!(&2i32, node_map.get(&g.from_index(2)).unwrap());
}
```

Run it with cargo run. If the assertion passes, the graph was built, the search ran and the index conversion worked. The README then shows the MST step and the DOT output, where Dot::with_config(&mst, &[Config::EdgeNoLabel]) produces a graph block suitable for Graphviz. Two optional features matter here: dot_parser enables parsing graphs from DOT strings and files, and serde-1 enables serialization for Graph, StableGraph and GraphMap.

## Where petgraph is the wrong tool

The README carries a warning that is easy to skim past: the version on the trunk branch is a new development version currently transitioning to a multi-crate layout and a new architecture, and the previous release lives on the 0.8 branch. The workspace manifest confirms the direction, listing crates/core, crates/petgraph and serialization-tests as members, and setting edition 2024 with rust-version 1.91 for the workspace while the README still states support for Rust 1.64 and later. Those two numbers describe different lines. If your project tracks trunk, you are consuming an API that the project itself describes as in transition. The practical move is to depend on the released 0.8.x versions, the most recent of which is petgraph@v0.8.3. Beyond versioning, petgraph is an in-process library with no server, no query language and no persistence layer. If your graph is large enough that it does not fit in memory, or if you want to query it from several services, a graph database is the appropriate shape of tool and petgraph is not. If you need parallel traversal across the whole graph, note that the rayon feature is documented as enabling parallel iterators for the underlying data in GraphMap specifically, not as a blanket parallel algorithm layer.

## petgraph against a graph database, and against writing your own adjacency list

The two alternatives worth weighing are a graph database and no dependency at all. A database such as Neo4j or a similar store keeps the graph outside your process, gives you a query language, handles data larger than memory and lets multiple services read the same graph. petgraph is the opposite: the graph is a value in your program, algorithms are function calls, and there is no network hop or server to operate. The difference in approach is where the graph lives and who owns its lifetime. The second alternative is rolling your own adjacency list, which is genuinely reasonable for a small fixed graph and a single traversal. petgraph earns its place once you want several algorithms over the same structure, or once you want to attach typed data to nodes and edges without writing your own index type. On the serialization side, the serde-1 feature covers Graph, StableGraph and GraphMap, so you can move a graph across a boundary without inventing a format. The DOT support cuts both ways: dot_parser reads DOT, and the Dot writer emits it, which makes Graphviz the natural viewer rather than a bespoke one.

## Maintenance, licence and what an upgrade actually costs

The repository is not archived, and the last push was on 2026-09-20. Releases have been arriving steadily: petgraph@v0.8.1 on 2025-04-07, petgraph@v0.8.2 on 2025-06-06 and petgraph@v0.8.3 on 2025-09-30. There is a CHANGELOG.md at the repository root, so version-to-version changes are documented rather than left to diffing. The upgrade cost is not uniform. Within the 0.8 line, expect incremental changes. Moving onto the trunk architecture is a different proposition, because the multi-crate split means the crate you depend on and the paths inside it can change; the README points readers to the 0.8 branch precisely so they do not have to absorb that transition. On licensing, the README states the crate is dual-licensed under Apache-2.0 or MIT, at your option, and the repository carries LICENSE-APACHE and LICENSE-MIT files. The workspace manifest uses the same expression, MIT OR Apache-2.0. That is the permissive pairing common in the Rust ecosystem, but whether it fits your distribution model is a question for your own legal review, not something the README answers.

## Conclusion

Adopt petgraph when you need an in-process graph with arbitrary node and edge payloads and algorithms you can call directly, and when depending on a released 0.8.x version fits your upgrade cadence. Do not adopt it if you need a stable API surface now and cannot pin to the 0.8 branch, because the README warns that trunk is a new development version in the middle of a multi-crate restructuring. Before committing, check which graph type matches your mutation pattern (Graph versus StableGraph versus GraphMap), confirm your toolchain meets the documented Rust 1.64 minimum for the released line, and decide whether the dot_parser or serde-1 features are needed, since both are opt-in.

## FAQ

### What are the four graph types in petgraph?

The README lists Graph, StableGraph, GraphMap and MatrixGraph. Graph is the default adjacency structure, StableGraph keeps node indices valid across removals, GraphMap keys nodes by a hashable value, and MatrixGraph stores adjacency as a matrix. All three of graphmap, stable_graph and matrix_graph are enabled by default.

### What is petgraph used for?

It provides graph data structures and algorithms in Rust, supporting directed and undirected graphs with arbitrary node and edge data. The README names path-finding, minimum spanning trees and graph isomorphisms among the included algorithms, and DOT export for visualization with Graphviz.

### What are the alternatives to petgraph in Rust?

The README does not name alternatives. The realistic choices are a graph database, which keeps the graph outside your process and adds a query language, or hand-writing an adjacency list over Vec and HashMap, which works for a single small traversal but means building your own index type and neighbour iteration.

## Sources

- [License: Apache-2.0](https://github.com/petgraph/petgraph/blob/master/LICENSE)
- [petgraph/petgraph on GitHub](https://github.com/petgraph/petgraph)
- [Project website](https://docs.rs/petgraph/)
- [README](https://github.com/petgraph/petgraph/blob/master/README.md)
- [Releases](https://github.com/petgraph/petgraph/releases)

---

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