GUN: a CRDT graph database that syncs over the network by default
An open source cybersecurity protocol for syncing decentralized graph data.
At a glance
- What is it?
- GUN is a JavaScript graph store where every write is also a peer-to-peer sync event. It is a good fit for local-first apps that want realtime collaboration without running a central database, and a poor fit for anything that needs server-side queries or a stable versioned release.
- Who is it for?
- Adopt GUN if you are building a local-first JavaScript app where peers must see each other's writes in realtime and you can tolerate a graph API instead of SQL or Mongo-style queries. Do not adopt it if you need server-side aggregation, a documented storage engine, or a semver-stable release line, because the newest published release on the repository is 0.2019.413 from April 2019 and the README itself says to use npm or a CDN for the latest code.
- Can I use it commercially?
- Check first. The repository uses a licence we do not classify automatically, so read its LICENSE file before any commercial use.
- Is it still maintained?
- Yes. The repository last received commits 45 days ago.
- What is it written in?
- Mainly JavaScript, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem GUN solves: writes that are also sync events
Most JavaScript apps start with a database behind an API, and every realtime feature is bolted on afterwards: a websocket layer, a change feed, a conflict resolution pass. GUN inverts that. The README describes it as an ecosystem of tools for building community run and encrypted applications, and positions it as an Open Source Firebase or a Decentralized Dropbox. The target user is a frontend or full-stack JavaScript developer who wants the data layer to be the sync layer.
The concrete promise is in the feature list: multiplayer by default with realtime peer-to-peer state synchronization, graph data that can be used as key/value, tables or documents, and local-first, offline, decentralized operation with end-to-end encryption. The README also states that the Internet Archive and other apps run GUN in production, and that decentralized alternatives to Zoom, Reddit, Instagram, Slack, YouTube, Stripe and Wikipedia have pushed terabytes of daily P2P traffic on GUN. Treat those as claims from the project, not measurements you can reproduce from the repository alone.
Who it is not for matters as much. If your application is a reporting dashboard, a billing system, or anything where one server must be the authority on the current state, GUN's peer-to-peer merge model is working against you rather than for you.
How the graph and CRDT merge actually work
The README states that GUN's stack includes CRDT conflict resolution, and the quickstart shows the shape of the data model. You call GUN() to get an instance, then gun.get('mark').put({name: "Mark", email: "mark@gun.eco"}) writes a node under the key mark. Reading is gun.get('mark').on((data, key) => {...}), which the README describes as realtime updates, or .once() which grabs the data once with no subscription.
The interesting part is traversal. The README's second example builds a circular reference: cat = {name: "Fluffy", species: "kitty"}, mark = {boss: cat}, cat.slave = mark. Putting mark and then reading gun.get('mark').get('boss').get('name').once(...) returns the nested value, and gun.get('mark').get('boss').get('slave').once(...) walks back around the cycle. A comment in the example states that partial updates merge with existing data, which is the CRDT behaviour: a put is a merge into a node, not a replacement of a document.
Tables are sets. gun.get('list').set(gun.get('mark').get('boss')) adds an existing node to a set, gun.get('list').map().once(...) iterates the members, and gun.get('list').set({type: "cucumber", goal: "jumping cat"}) adds an inline object. Because set members are graph references, the same node can appear in several sets without being copied. That is the mechanism, and it is why the README can claim one data model covers key/value, tables and documents: they are all nodes and edges in the same graph.
Installing GUN and the first working script
The README gives two entry points. In the browser, load the script from a CDN: <script src="https://cdn.jsdelivr.net/npm/gun/gun.js"></script>. In Node, npm install gun, then run the bundled examples with cd node_modules/gun && npm start. The README notes that if npm fails you may need to mkdir node_modules first or use sudo.
The import lines are commented in the quickstart and they differ by environment: import GUN from 'gun' in ESM, GUN = require('gun') in NodeJS, and GUN = require('gun/gun') in React. That last one is worth reading twice, because pulling the full package into a React bundle is a different thing from pulling the core file.
A complete first script from the README is four statements: gun = GUN(); gun.get('mark').put({name: "Mark", email: "mark@gun.eco"}); gun.get('mark').on((data, key) => console.log("realtime updates:", data)); and a setInterval that writes a random number to gun.get('mark').get('live') every 9 milliseconds. The interval is there to make the realtime subscription visibly fire. There is no schema, no migration step and no server configuration in the quickstart. The README points to an interactive tutorial at gun.eco/docs/Todo-Dapp and says it takes about five minutes for an average developer, and to an online demo at try.axe.eco.
Where GUN is the wrong tool
The release history on the repository is the first warning. The most recent listed release is 0.2019.413 from April 2019, and its own label says it is out of date and to use npm or CDN for the latest. Below that are 0.9.999998 from January 2019 and 0.7.0 from April 2017. If your dependency policy requires tagged releases with changelogs, GUN's published release line does not give you that, even though the default branch shows activity in 2026.
The second warning is the query model. GUN gives you get, put, on, once, set and map. There is no join, no aggregate, no index you declare in the quickstart, and no server-side query planner described in the material. If you need to compute a monthly total across every user, you are pulling data to a client and reducing it there, or you are writing that aggregation yourself somewhere else.
The third is the licence. The repository metadata reports NOASSERTION, which means GitHub could not map the licence file to a known identifier. The README does not state licence terms in the text provided. Before you ship GUN inside a product, read the licence file in the repository yourself and get your own advice; nothing in this article should be read as legal guidance.
Finally, encryption is opt-in and separate. The README links to SEA and Cartoon Cryptography for cryptographic security, but the quickstart writes plaintext to gun.get('mark'). Data is not encrypted because you installed GUN.
GUN versus a plain CRDT library such as Automerge
The closest comparison is a CRDT library rather than a database. Automerge, for example, gives you a document that merges deterministically and leaves the transport to you: you decide whether changes travel over a websocket, a file, or a git repository. GUN bundles the transport. Its peers connect and relay writes as part of the runtime, and the README's feature list treats realtime p2p synchronization as the default state of the system rather than an add-on.
That difference sets the failure modes. With Automerge you must run and secure the sync server yourself, but you know exactly where the bytes go. With GUN the relay is part of the model, and the README's emphasis on community run and decentralized operation means the topology is a design decision you inherit. GUN's graph also allows the circular references shown in the README, which a document-oriented CRDT does not express the same way.
If you want a CRDT with no networking opinions, take Automerge. If you want the networking to be the product, GUN is built around that. The trade is control over transport for having transport solved.
Maintenance cost and what to verify before adopting
Budget for reading source rather than changelogs. With the newest published release dated 2019 and the repository still receiving pushes, the practical upgrade path is the npm package or the CDN build, which means your version is whatever the registry serves that day. Pin an exact version and vendor the file if reproducibility matters to you.
The modular stack adds its own cost. The README lists CRDT conflict resolution, SEA encryption, RAD storage serialization, DAM mesh networking, routing algorithms, a panic-server test harness, and a CPU-scheduled JSON parser called yson that exists to prevent UI lag. Each of those is a separate thing to understand when something misbehaves, and the README presents them as independent tools rather than one monolith.
Two checks are worth doing before you write production code. First, open gun.eco/docs and confirm which storage adapter and relay configuration match your deployment, because the quickstart does not cover persistence. Second, read the licence file at the repository root, since the metadata reports NOASSERTION and the README text provided does not resolve it. If either check comes back unclear for your use case, that is the signal to prototype on a throwaway branch before committing a team to it.
Editorial conclusion
Adopt GUN if you are building a local-first JavaScript app where peers must see each other's writes in realtime and you can tolerate a graph API instead of SQL or Mongo-style queries. Do not adopt it if you need server-side aggregation, a documented storage engine, or a semver-stable release line, because the newest published release on the repository is 0.2019.413 from April 2019 and the README itself says to use npm or a CDN for the latest code. Before committing, verify two things against the docs at gun.eco/docs: which storage adapter you will run in production, and whether the SEA encryption module covers your threat model, since the README links to SEA and Cartoon Cryptography but does not specify the primitives in the repository text.
Community notes