GraphNeuralNetworks.jl: GNN layers for Flux and Lux users in Julia
Graph Neural Networks in Julia
At a glance
- What is it?
- The JuliaGraphs monorepo ships two frontend packages, one for Flux.jl and one for Lux.jl, over a shared message-passing core. It is a good fit if your graph data is already in Julia and you want GPU support without leaving the language.
- Who is it for?
- Adopt it if your pipeline is already Julia and your graphs fit the GNNGraphs data structures, because the Flux and Lux frontends share one message-passing core and the layers come with node, edge and graph-level examples. Do not adopt it if you need a layer the shared core does not implement and you are unwilling to write it yourself, or if your team's graph tooling and pretrained checkpoints live in Python.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 34 days ago.
- What is it written in?
- Mainly Julia, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 22, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
What GraphNeuralNetworks.jl is for, and who ends up using it
The problem is narrow and specific: you have a dataset that is not a grid of pixels or a sequence of tokens, and you want to train on it in Julia. The README describes the repository as "Libraries for deep learning on graphs in Julia", using either Flux.jl or Lux.jl as the backend framework. That framing matters more than it first appears, because the repository is not one package. It is four, and only two of them are meant to be installed by an end user.
GraphNeuralNetworks.jl is the frontend for Flux users. GNNLux.jl is the frontend for Lux users. GNNGraphs.jl holds the graph data structures and helper functions, and GNNlib.jl implements the message-passing framework on top of gather/scatter or sparse matrix multiplication. The README states plainly that GNNlib is "not intended for direct use by end-users but is re-exported by the frontend packages", and the same re-export applies to GNNGraphs. So the install surface is one package, chosen by which training framework you already use.
The audience is therefore people who have already committed to Julia for their machine learning work. If you are reaching for this library, you are probably not choosing between Julia and Python from scratch. You are choosing whether to move a graph workload out of Python to keep it next to the rest of your Julia code, or whether to keep it in Python and accept the split.
The four-package split and the gather/scatter core
The layering is the most interesting design decision in the repository, and it is worth understanding before you file an issue about a missing layer.
GNNlib.jl sits at the bottom. According to the README it "implements the message-passing framework based on the gather/scatter mechanism or sparse matrix multiplication" and "includes shared implementations for the layers used by the two frontend packages". That last clause is the key one. The convolution logic is written once, and both the Flux frontend and the Lux frontend call into it. The difference between GraphNeuralNetworks.jl and GNNLux.jl is not the math. It is how parameters are held and how the model is called, which is exactly the difference between Flux and Lux as frameworks.
Above that, GNNGraphs.jl supplies the graph representation and the helper functions. The README lists Graphs.jl integration as a feature, so graphs built with the wider JuliaGraphs ecosystem are meant to interoperate rather than require conversion into a private format.
At the top, the two frontends expose the layers and re-export the lower packages so that a user never types GNNlib or GNNGraphs in a using statement. This is a sensible arrangement. It also means that if a layer exists in one frontend, the shared implementation is likely already there, and the gap is more often in the frontend wrapper than in the arithmetic. When something is missing, that is the first place to look.
One consequence is worth stating directly: because the core is shared, the two frontends are not independent projects with independent roadmaps. A change in GNNlib reaches both. The recent releases show GNNlib-v1.4.0 and GNNlib-v1.3.0 landing on the same day in July 2026, with the frontend release GraphNeuralNetworks-v0.6.12 following at the end of that month. The version numbers in the two frontends do not track each other, which is normal for a monorepo but does mean that "which version are you on" is a two-part answer.
Installing GraphNeuralNetworks.jl or GNNLux.jl and running a first layer
Both packages are registered in the General registry, so installation goes through the Julia package manager. Pick one line depending on your training framework. The README is explicit that you do not install the lower-level packages yourself.
For Flux users:
pkg> add GraphNeuralNetworksFor Lux users:
pkg> add GNNLuxAfter the add completes, the package and its re-exported dependencies are available with a single using statement. The README does not print a worked example inline; it points to the examples folder and the notebooks folder in the GraphNeuralNetworks directory, and to the documentation site at juliagraphs.org for "a comprehensive introduction to the library". Those example directories are the intended first stop, and they cover node, edge and graph-level tasks, which are the three task shapes the library is organized around.
The feature list is what you should check against your own problem before writing any code. The README lists common graph convolutional layers, computation on batched graphs, custom layer definitions, CUDA and AMDGPU support, Graphs.jl integration, examples for node, edge and graph-level machine learning, and heterogeneous and dynamical graphs and convolutions. Batched graphs and custom layers are the two that most often decide whether a library is usable for a real project rather than a tutorial. If your graphs have varying sizes, the batching support is the feature you are really adopting.
The README does not document a rollback procedure, a version pinning recipe, or a compatibility matrix between frontend and core versions. If you need to reproduce an environment exactly, that information is not in the README and you will have to read the Project.toml files and the changelog in the repository.
Where the shared core becomes a constraint
The single most likely failure mode is not a bug. It is a missing layer.
Because GNNlib.jl holds "shared implementations for the layers used by the two frontend packages", the set of available convolutions is bounded by what someone has written into that shared core. The README says the library implements "common graph convolutional layers" and supports "custom layer definitions", and that pairing is the honest description of the trade-off. You get the common cases off the shelf, and everything else is your code. A paper published last month with a new aggregation scheme will almost certainly not be in the release you installed, and the answer is to implement it against the message-passing primitives rather than to expect it upstream.
There is a second constraint that follows from the same architecture. The README lists CUDA and AMDGPU support, but it does not claim they are equally mature, and it gives no benchmark numbers for either. If your work depends on a specific accelerator, the documentation site is where you check the current state, not the feature bullet. Treating a feature list as a support guarantee is how people end up debugging a backend that was never described as production ready.
The third case where this is the wrong tool is organizational rather than technical. If your team's graph models, pretrained checkpoints, and deployment tooling all live in Python, adopting a Julia library splits the stack in two. The README's own acknowledgments note that the library is "largely inspired by" PyTorch Geometric, Deep Graph Library and GeometricFlux.jl, so the concepts will look familiar to someone coming from those projects. Familiar concepts are not the same as portable weights.
PyTorch Geometric and DGL: same ideas, different language boundary
The README names PyTorch Geometric and Deep Graph Library directly in its acknowledgments, and it names GeometricFlux.jl as well. That makes the comparison unusually easy to state, because the project itself frames the relationship as inspiration rather than competition.
The real difference is not the layer catalog. It is where the language boundary sits. PyTorch Geometric and DGL put graph learning inside Python, alongside the rest of the PyTorch or deep learning ecosystem, which means the surrounding tooling (data loaders, experiment trackers, serving stacks, pretrained checkpoints) is in the same language as the model. GraphNeuralNetworks.jl puts graph learning inside Julia, alongside Graphs.jl and the rest of the JuliaGraphs ecosystem, which means your graph construction, your analysis code and your model can share data structures without a serialization step.
GeometricFlux.jl is the closer relative, since it is also a Julia project and also Flux-oriented, and the README lists it as an inspiration. The repository structure here is the distinguishing feature: rather than one package tied to one framework, the shared GNNlib core serves both a Flux frontend and a Lux frontend. If you are on Lux, that matters, because Lux's explicit parameter handling is a different programming model from Flux's implicit one, and a library that only targets Flux would leave you wrapping things yourself.
The trade-off is ecosystem size. The README describes what this library does; it makes no claim about the number of available pretrained models or third-party extensions. If your project depends on those, the Python projects are where they are.
Maintenance, licence and what an upgrade actually costs
The repository is not archived, and the last push was on 2026-08-26. That is recent enough that the project is clearly being worked on, and the release history supports the same reading: GNNlib-v1.3.0 and GNNlib-v1.4.0 both landed on 2026-07-22, and GraphNeuralNetworks-v0.6.12 followed on 2026-07-31.
The upgrade cost is shaped by the monorepo. Because the frontends depend on GNNlib and GNNGraphs, a change in the shared core can reach both frontends at once, and the frontend version numbers do not move in lockstep with the core's. The repository ships a CHANGELOG.md at the top level, which is where you check before bumping, and each package has its own Project.toml with the compatibility bounds. The README does not describe a deprecation policy or a support window, so there is no documented promise about how long an older frontend version keeps working against a newer core. That is a real gap if you are pinning versions for a long-lived service.
The licence is MIT. In practical terms that is a permissive licence with minimal conditions, and it is compatible with the way most research and commercial Julia code is distributed. This is not legal advice; if you are redistributing the library inside a product, read the LICENSE file in the repository root and talk to someone qualified about your specific situation.
If you use the library in a scientific publication, the README asks for a citation to the JMLR paper by Carlo Lucibello and Aurora Rossi, with a BibTeX entry provided in the README itself.
Editorial conclusion
Adopt it if your pipeline is already Julia and your graphs fit the GNNGraphs data structures, because the Flux and Lux frontends share one message-passing core and the layers come with node, edge and graph-level examples. Do not adopt it if you need a layer the shared core does not implement and you are unwilling to write it yourself, or if your team's graph tooling and pretrained checkpoints live in Python. Before committing, verify which frontend matches your training loop, check that the layer you need exists in the current docs for that frontend, and confirm your accelerator path by reading the CUDA and AMDGPU sections of the documentation rather than assuming both are equally exercised.
Frequently asked questions
Do I install GraphNeuralNetworks.jl or GNNLux.jl?
It depends on your training framework. GraphNeuralNetworks.jl is the frontend for Flux.jl users and GNNLux.jl is the frontend for Lux.jl users. You do not install GNNGraphs or GNNlib directly, because their functionality is re-exported by the frontend packages.
Does GraphNeuralNetworks.jl support CUDA and AMDGPU?
The README lists support for CUDA and AMDGPU as a feature of both frontend packages. It does not give performance figures or claim the two backends are equally mature, so check the documentation site for the current state of the one you plan to use.
Can I define my own graph convolutional layer in GraphNeuralNetworks.jl?
Yes. Custom layer definitions are listed as a supported feature, and the shared GNNlib.jl core implements the message-passing framework based on gather/scatter or sparse matrix multiplication that custom layers build on. The README does not walk through the process, so the documentation site is the place to look.
Which task types does GraphNeuralNetworks.jl have examples for?
The README points to examples of node, edge and graph-level machine learning tasks in the examples folder of the GraphNeuralNetworks package, with additional notebooks in a separate folder. Those are the three task shapes the library is organized around.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/juliagraphs-graphneuralnetworks-jl)
Community notes