AgensGraph
Overview
AgensGraph is a multi-model graph database built on PostgreSQL. Version 2.17.0 tracks PostgreSQL 17.10, so everything you already know about PostgreSQL applies unchanged: ACID transactions, MVCC, roles and permissions, indexes, pg_dump and the whole driver ecosystem. On top of that, it adds a native property graph model and the openCypher query language, with partial ISO/GQL support.
A multi-model engine means you do not have to choose between models. A graph traversal and a SQL join can run against the same database, in the same transaction, without an ETL hop between two systems. That makes AgensGraph a natural fit for fraud rings, recommendation graphs, network and asset topologies, knowledge graphs and identity resolution, where the relationships matter as much as the rows.
This guide covers deploying and using AgensGraph on Ubuntu 24.04 on Azure with SecureAnyCloud Azure Marketplace images. The image is built from source at the pinned upstream release tag against Ubuntu 24.04's own OpenSSL 3, zlib, readline and ICU libraries. The cryptography AgensGraph links against is therefore the distribution's, so ordinary unattended-upgrades on your VM keeps it current.
Security by design, no baked-in credential. The agens superuser role is passwordless by construction. The database is initialised with peer authentication on the local socket, and no password is ever set at build time, so the captured image has no default or blank password to discover. On first boot, each VM generates a unique password for the agens role and a unique self-signed TLS server certificate. It writes them to the root-only file /root/agensgraph-credentials.txt and then enables TLS. Remote clients are accepted only over TLS (hostssl with scram-sha-256). Until first boot creates the certificate, the database is not reachable off the box at all.
What you get:
- AgensGraph 2.17.0 (PostgreSQL 17.10 base), built from source and running under systemd as
agensgraph.service - The
agensinteractive client and the full PostgreSQL tool set (pg_dump,pg_restore,pg_basebackup,createdb,pg_isreadyand the rest), all on the defaultPATH - A default database
graphdbcontaining a small demo property graph, so you can run a real Cypher traversal the moment the VM boots - A per-VM superuser password and a per-VM TLS certificate generated on first boot and written to a root-only credentials file
- No swap in the image, with the server tuned to fit a
Standard_B2sin RAM
Deploying the VM
Launch the image from the Azure Marketplace as you would any other VM. The recommended size is Standard_B2s (2 vCPU / 4 GiB), which the shipped postgresql.conf is tuned for. Larger graphs benefit from more memory, so raise shared_buffers and effective_cache_size in proportion if you move to a bigger SKU.
AgensGraph listens on TCP 5432. The Azure network security group (NSG) is your first line of defence. Open port 5432 only to the application subnets or client addresses that need it, never to the whole internet. TLS and the per-VM password are the second and third layers, but only the NSG keeps unwanted traffic off the box entirely.
First boot
The first time the VM boots, agensgraph-firstboot.service runs once and then disables itself. It performs these tasks:
- Waits for AgensGraph to accept local connections.
- Creates a per-VM self-signed TLS server certificate.
- Sets
ssl = onand reloads the server. - Generates a unique password for the
agenssuperuser role. - Writes
/root/agensgraph-credentials.txt(mode 600, owned by root). - Writes a message-of-the-day pointer.
This normally completes within a few seconds of the database accepting connections. You do not need to do anything.
Retrieving your per-VM credentials
The password is unique to your VM and is stored in plain text only in this one root-only file:
sudo cat /root/agensgraph-credentials.txtExpected output (your host and password will differ):
# AgensGraph — generated on first boot by agensgraph-firstboot.service.
# This password is UNIQUE to this VM. Store it somewhere safe; it is shown in
# plain text only here. Rotate with:
#
sudo -u agens agens -c "ALTER ROLE agens PASSWORD '<new>'"
# then update this file to match. agensgraph.host=10.0.0.10 agensgraph.port=5432 agensgraph.role=agens agensgraph.password=<unique to your VM> agensgraph.database=graphdb agensgraph.sslmode=requireCopy the password into your secret store now. To rotate it later, run sudo -u agens agens -c "ALTER ROLE agens PASSWORD '<your-new-password>'" and update the file to match.
Checking service health
sudo systemctl status agensgraph --no-pagerExpected output:
● agensgraph.service - AgensGraph 2.17.0 multi-model graph database Loaded: loaded (/etc/systemd/system/agensgraph.service; enabled; preset: enabled) Active: active (running) since Sun 2026-07-26 16:02:57 UTC Main PID: 40859 (postgres) CGroup: /system.slice/agensgraph.service ├─40859 /usr/local/agensgraph/bin/postgres -D /var/lib/agensgraph/data ├─40860 "postgres: logger " ├─40861 "postgres: checkpointer "Confirm the server is accepting connections and report its version:
sudo -u agens pg_isready/var/run/agensgraph:5432 - accepting connectionssudo -u agens agens -d graphdb -qtAc "SELECT version();"PostgreSQL 17.10 (AgensGraph 2.17.0) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 13.3.0-6ubuntu2~24.04.1) 13.3.0, 64-bitThe version string names both layers: the PostgreSQL release that provides the storage and SQL engine, and the AgensGraph release that adds the graph model.
Connecting locally
agens is the AgensGraph interactive client. It is PostgreSQL's psql with Cypher support, and every psql flag works the same way. On the VM itself, you connect through the local Unix socket with peer authentication, so no password is needed:
sudo -u agens agens -d graphdb -qtAc "SELECT current_database(), current_user;"graphdb|agensFor an interactive session, run sudo -u agens agens -d graphdb and type queries at the graphdb=# prompt. Use \q to quit and \? for the client's help.
Querying the demo graph
The graphdb database ships with a small property graph named demo: three :person vertices joined by two :knows edges. A graph is selected with SET graph_path, which behaves like PostgreSQL's search_path.
List the vertices and their properties:
sudo -u agens agens -d graphdb -c "SET graph_path = demo; MATCH (p:person) RETURN p.name AS name, p.city AS city ORDER BY p.name;"SET name | city ---------+----------- "alice" | "London" "bob" | "Leeds" "carol" | "Bristol" (3 rows)Property values come back as JSON values, which is why they are quoted. A vertex property is a jsonb field, so it can hold a string, a number, an array or a nested object.
Next, walk the relationships. This is the query shape a graph database exists for:
sudo -u agens agens -d graphdb -c "SET graph_path = demo; MATCH (a:person)-[r:knows]->(b:person) RETURN a.name AS from, b.name AS to, r.since AS since ORDER BY a.name;"SET from | to | since ---------+---------+------- "alice" | "bob" | 2019 "bob" | "carol" | 2021 (2 rows)Edges carry properties too. Here, since records when each relationship was formed.
The real advantage shows up with a variable-length traversal. [:knows*1..2] follows the knows relationship between one and two hops, so alice reaches bob directly and carol through bob, in a single query with no self-join:
sudo -u agens agens -d graphdb -c "SET graph_path = demo; MATCH (a:person {name: 'alice'})-[:knows*1..2]->(b:person) RETURN b.name AS reachable;"SET reachable ----------- "bob" "carol" (2 rows)Widening the traversal to *1..5 changes only two characters. The equivalent in plain SQL is a recursive common table expression that you would have to rewrite for every new depth and shape.
Connecting remotely over TLS
Remote clients are accepted only over TLS. Any libpq client works, including agens, psql, JDBC, Python (psycopg), Node (pg) and Go (pgx), because the wire protocol is PostgreSQL's.
Connect with the values from your credentials file and sslmode=require:
sudo bash -c 'PW=$(sed -n "s/^agensgraph.password=//p" /root/agensgraph-credentials.txt); agens "host=127.0.0.1 port=5432 dbname=graphdb user=agens password=$PW sslmode=require" -c "SELECT ssl, version AS tls_version, cipher FROM pg_stat_ssl WHERE pid = pg_backend_pid();"'ssl | tls_version | cipher -----+-------------+------------------------ t | TLSv1.3 | TLS_AES_256_GCM_SHA384 (1 row)The value ssl = t confirms that the session is encrypted, negotiated here as TLS 1.3. From your workstation, substitute your VM's public address:
agens "host=<your-vm-public-ip> port=5432 dbname=graphdb user=agens password=<your-per-vm-password> sslmode=require"
The certificate generated on first boot is self-signed, so sslmode=require encrypts the connection without verifying the issuer. To have clients verify the server as well, replace /var/lib/agensgraph/data/server.crt and server.key with a certificate from your own CA. Then distribute the CA certificate to your clients and have them connect with sslmode=verify-full.
Creating your own graph
Create a graph, add data and query it. These statements modify your database, so they are shown inline rather than as a runnable block. Run them in an interactive agens session or pass them with -c.
Create a graph and make it the default for the session: CREATE GRAPH social; then SET graph_path = social;
Create vertices with a label and properties: CREATE (:account {handle: 'ada', joined: 2021});
Create a relationship between two existing vertices: MATCH (a:account {handle: 'ada'}), (b:account {handle: 'grace'}) CREATE (a)-[:follows {weight: 1.0}]->(b);
Update a property on a matched vertex: MATCH (a:account {handle: 'ada'}) SET a.verified = true;
Delete a vertex and its relationships: MATCH (a:account {handle: 'ada'}) DETACH DELETE a;
Because AgensGraph is PostgreSQL underneath, all of this is transactional. Wrap statements in BEGIN / COMMIT, and a failed load rolls back cleanly.
For performance on larger graphs, index the properties you filter on with CREATE PROPERTY INDEX ON account (handle);. AgensGraph 2.17 also supports expression property indexes, including pgvector HNSW indexes over a ::vector(n) cast and GIN indexes over to_tsvector(...). These indexes make vector, full-text and hybrid search over graph properties possible.
Mixing SQL and Cypher
Both languages address the same database. Ordinary SQL works exactly as it does in PostgreSQL:
sudo -u agens agens -d graphdb -c "SELECT schemaname, tablename FROM pg_tables WHERE schemaname = 'demo' ORDER BY tablename;"Create ordinary relational tables with CREATE TABLE and query them with SELECT, alongside your graphs, in one transaction. Vertex and edge labels are stored as tables in a schema named after the graph, which is why the query above lists them. The graph is not a bolt-on. It is native storage in the same engine.
Backup and restore
The standard PostgreSQL tooling covers graphs as well as tables, and is on the default PATH.
Dump the whole database, graphs included, and confirm the archive was written:
sudo -u agens pg_dump -d graphdb -Fc -f /tmp/graphdb.dump && sudo ls -lh /tmp/graphdb.dump-rw-rw-r-- 1 agens agens 12K Jul 26 16:08 /tmp/graphdb.dumpRestore into a new database with sudo -u agens createdb graphdb_restored, followed by sudo -u agens pg_restore -d graphdb_restored /tmp/graphdb.dump. Graphs survive the round trip intact, and the restored database returns the same traversal results as the original.
For a physical backup of the whole cluster, use pg_basebackup. AgensGraph 2.17 inherits PostgreSQL 17's incremental backup support, so pg_basebackup --incremental, combined later with pg_combinebackup, keeps routine backups small.
Move dumps off the VM promptly, because a backup on the same disk as the database does not protect against disk loss.
Where things live
Path Purpose
/usr/local/agensgraph Installation prefix (binaries in bin, libraries in lib)
/usr/local/bin agens and the PostgreSQL tools, on the default PATH
/var/lib/agensgraph/data Data directory, including postgresql.conf and pg_hba.conf
/var/log/agensgraph Server logs, rotated daily
/var/run/agensgraph Unix socket directory
/root/agensgraph-credentials.txt Per-VM credentials, mode 600, root only
/etc/systemd/system/agensgraph.service systemd unit
Show the effective configuration at any time with this command:
sudo -u agens agens -d graphdb -c "SELECT name, setting FROM pg_settings WHERE name IN ('listen_addresses','port','ssl','shared_buffers','work_mem','data_directory') ORDER BY name;"After editing postgresql.conf, apply the change with sudo systemctl reload agensgraph for settings that support reload, or sudo systemctl restart agensgraph for those that need a restart. The pending_restart column of the pg_settings view shows which applies.
Tuning
The shipped configuration is sized for a Standard_B2s: shared_buffers 512MB, effective_cache_size 2GB, work_mem 8MB, maintenance_work_mem 128MB. The image deliberately ships with no swap. Swap on a cloud VM turns a memory shortage into unpredictable latency rather than a clean failure. If your working set outgrows the VM, move to a larger SKU instead of adding a swapfile.
When you scale up, start with shared_buffers at about a quarter of RAM and effective_cache_size at about three quarters. Raise work_mem carefully, because it is allocated per sort or hash node, not per connection, so a complex query can use several multiples of it at once.
Security checklist
- Restrict the NSG. Allow port 5432 only from the subnets or addresses that need it.
- Rotate the per-VM password into your secret store, and treat
/root/agensgraph-credentials.txtas a sensitive file. - Create a least-privilege role for your application rather than connecting as the
agenssuperuser. Create one withCREATE ROLE app LOGIN PASSWORD '<your-password>';and grant only what it needs. - Tighten
pg_hba.conf. The shipped file accepts TLS connections from0.0.0.0/0. Narrow that to your application subnet CIDR. - Replace the self-signed certificate with one from your own CA if clients should verify the server, then move them to
sslmode=verify-full. - Leave
unattended-upgradesenabled so OpenSSL and the rest of the base system keep receiving security updates.
Troubleshooting
The service does not start. Check the unit, then the server's own log:
sudo systemctl status agensgraph --no-pagersudo tail -n 40 /var/log/agensgraph/$(sudo ls -1 /var/log/agensgraph | tail -1)The credentials file is missing. agensgraph-firstboot.service writes it on the first boot only. Check what happened:
sudo tail -n 30 /var/log/sac/sac-firstboot.logA remote client cannot connect. Work outward from the server. Confirm the server is listening locally with sudo -u agens pg_isready, and confirm TLS is on with sudo -u agens agens -d graphdb -qtAc "SHOW ssl;". Then check that the Azure NSG allows port 5432 from your address. Remote connections without TLS are refused by design, so a client without sslmode=require is rejected.
A Cypher query unexpectedly returns nothing. The most common cause is graph_path pointing at a different graph. Confirm which graph you are querying:
sudo -u agens agens -d graphdb -c "SET graph_path = demo; SHOW graph_path;"Further reading
- AgensGraph documentation: https://tech.skaiworldwide.com/docs
- AgensGraph source and releases: https://github.com/skaiworldwide-oss/agensgraph
- openCypher language reference: https://opencypher.org
- PostgreSQL 17 documentation: https://www.postgresql.org/docs/17/
Support
SecureAnyCloud publishes this image. For help with the image itself, contact sales@secureanycloud.com.
Deploy on Azure
Launch AgensGraph on Ubuntu 24.04 on Azure with 24/7 support from SecureAnyCloud.
View on Marketplace
Need Help?
Our support team is available 24/7.
sales@secureanycloud.com