# Aerospike Graph Service (AGS)
> An [Apache TinkerPop][tinkerpop]-compatible graph database engine backed
> by [Aerospike][aerospike]. Designed for low-latency graph traversals at
> scale: terabytes of vertices and edges, thousands of concurrent
> queries, single-digit-millisecond p99, while keeping a plain,
> Gremlin-standard interface on the wire.
[](LICENSE)
[](https://tinkerpop.apache.org)
[](https://adoptium.net)
> Documentation: User guides and deployment procedures at [aerospike.com/docs/graph](https://aerospike.com/docs/graph).
---
## What is Aerospike Graph Service
Aerospike Graph Service (AGS) is a JVM process that speaks the standard
TinkerPop Gremlin wire protocol over WebSocket and stores its data in
an Aerospike cluster. Use any Gremlin driver variant
(`gremlin-python`, `gremlin-javascript`, `tinkerpop-client` in Java,
and other TinkerPop-compatible drivers), issue normal Gremlin traversals and the
service translates them into efficient Aerospike operations, applies
query-planning optimizations specific to Aerospike's data model, and
streams results back to the driver.
### Why another graph database?
- Aerospike as the storage tier. Inherit Aerospike's strong
consistency, predictable sub-millisecond reads, horizontal scale,
hybrid-memory architecture, and cross-datacenter replication. Graph
state is another flavor of workload on top of a high-performance, battle-tested
key-value store.
- Standard Gremlin on the wire. Anything that speaks TinkerPop 3.7.x works. No bespoke query language, no
custom drivers. TinkerPop 3.8 is not supported because of breaking changes in that line.
- Aerospike-native data layout. Vertices and edges are stored in
a `packed` on-disk layout tuned for Aerospike's record structure,
keeping adjacency information co-resident with the vertex so that
most traversal hops resolve in a single Aerospike read. See
[`docs/DATA_MODEL_DESIGN.md`](docs/DATA_MODEL_DESIGN.md).
- Scale-out OLAP. The Spark-backed OLAP module lets you run
`GraphComputer` jobs (for example PageRank, connected components, custom
VertexPrograms) over the full graph without holding it in a single
JVM.
- Bulk loading. A Spark-backed bulk loader ingests CSV / GraphML /
GraphSON vertex and edge files directly into the Aerospike data
model, bypassing the query path for order-of-magnitude faster
initial loads.
## Quickstart
```text
┌──────────────┐ Gremlin (ws://host:8182) ┌─────────────────────┐ Aerospike ┌─────────────────┐
│ Your app │ ───────────────────────────> │ Graph Service │ ───────────> │ Aerospike │
│ (any lang) │ <─────────────────────────── │ (this container) │ <─────────── │ cluster │
└──────────────┘ └─────────────────────┘ └─────────────────┘
```
### Quickstart with Docker Compose
If you do not already have an Aerospike cluster, [`graph-service-examples/`](graph-service-examples)
ships a `docker-compose.yaml` that starts AGS, Aerospike Database, and Zipkin in one command:
```bash
cd graph-service-examples
docker compose up -d
```
[`graph-service-examples/`](graph-service-examples) also includes runnable example
applications and sample datasets, plus a bulk-load guide. The
official step-by-step walkthrough is at
[aerospike.com/docs/graph/quick-start](https://aerospike.com/docs/graph/quick-start).
The rest of this section shows how to run AGS in Docker. Pick one path below.
See [Deploy Aerospike Graph Service with Docker](https://aerospike.com/docs/graph/deploy/docker)
for the full deployment guide.
### Prerequisites
Before you run AGS in Docker, you need:
- An Aerospike Database deployment compatible with this release. AGS works with
Community Edition; if you choose Enterprise or Standard Edition, provide the
feature key required by that database edition.
- An Aerospike Database version compatible with this release. See
[`docs/COMPATIBILITY.md`](docs/COMPATIBILITY.md).
- A namespace that already exists on the cluster with
[`default-ttl`](https://aerospike.com/docs/database/reference/config#namespace__default-ttl)
set to `0`. See [TTL on the Aerospike namespace](#ttl-on-the-aerospike-namespace) below.
- If access control is enabled on Aerospike, the AGS database user needs `sys-admin`
and `read-write` privileges.
### Aerospike Database in Docker
Use this path if you do not already have Aerospike running. It starts Aerospike Database
and AGS together on a shared Docker network. Do not also run
[Run AGS with Docker](#run-ags-with-docker) afterward.
1. Pull the images:
```bash
docker pull aerospike/aerospike-server-enterprise:latest
docker pull aerospike/aerospike-graph-service:latest
```
2. Start Aerospike Database and AGS:
```bash
docker network create ags-net 2>/dev/null || true && \
docker rm -f aerospike graph 2>/dev/null || true && \
docker run -d --name aerospike --network ags-net \
aerospike/aerospike-server-enterprise:latest && \
until docker exec aerospike asinfo -v 'status' 2>/dev/null | grep -q ok; do sleep 1; done && \
docker run -d --name graph --network ags-net --restart unless-stopped \
-p 8182:8182 \
-e aerospike.client.namespace="test" \
-e aerospike.client.host="aerospike:3000" \
aerospike/aerospike-graph-service:latest
```
`aerospike:3000` is the Aerospike container name on `ags-net` plus the default service
port. `test` is the default namespace in the Aerospike Docker image. Change these only
if you configured Aerospike differently. This example uses the Enterprise image;
you can use Community Edition instead when your deployment does not need an
Enterprise-only database capability.
### Run AGS with Docker
Use this path only when Aerospike is already running somewhere else (on the host, on
another machine, or in a container you started separately). Skip this section if you
used [Aerospike Database in Docker](#aerospike-database-in-docker) above.
1. Pull the AGS Docker image:
```bash
docker pull aerospike/aerospike-graph-service:latest
```
2. Run the AGS container:
```bash
docker run -d --name graph \
-p 8182:8182 \
-e aerospike.client.namespace="NAMESPACE" \
-e aerospike.client.host="HOSTNAME:PORT" \
aerospike/aerospike-graph-service:latest
```
- `HOSTNAME:PORT`: hostname or IP of an Aerospike seed node and its service port. The
default Aerospike service port is `3000`. Examples: `db.example.com:3000` for a remote
cluster, or `host.docker.internal:3000` when Aerospike runs on the host outside Docker.
Do not use `localhost` here. Inside the AGS container, `localhost` refers to the AGS
container itself, not your machine.
- `NAMESPACE`: name of an existing namespace on that cluster, for example `test`. List
namespaces with [`asadm`](https://aerospike.com/docs/database/tools/asadm) (`show namespaces`).
If Aerospike is running in a Docker container, put AGS on the same Docker network and
use the Aerospike container name as `HOSTNAME` (for example `aerospike:3000`), or get
its IP address with:
```bash
docker inspect -f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' AEROSPIKE_CONTAINER_ID
```
Replace `AEROSPIKE_CONTAINER_ID` with the Aerospike container ID or name.
### Server output
AGS logs to `stdout`. When the container is started with `-d`, follow the logs with:
```bash
docker logs -f graph
```
After startup completes, the log includes:
```text
Channel started at port 8182.
```
### TTL on the Aerospike namespace
If AGS fails to start with a `default-ttl` error, set the namespace TTL to `0`:
1. Start the Aerospike Tools container:
```bash
docker run -it aerospike/aerospike-tools asadm -h HOSTNAME
```
Replace `HOSTNAME` with the hostname or IP of your Aerospike server. If Aerospike is
running on a Docker network (for example `ags-net` from [Aerospike Database in Docker](#aerospike-database-in-docker)):
```bash
docker run -it --network ags-net aerospike/aerospike-tools asadm -h aerospike
```
2. At the `Admin>` prompt, enable dynamic configuration:
```text
enable
```
3. Set `default-ttl` to `0`:
```text
manage config namespace NAMESPACE param default-ttl to 0
```
4. Restart AGS:
```bash
docker start graph
```
### Connect with a Gremlin driver
With AGS running and port 8182 published (as in the steps above), connect to it from
your application using any TinkerPop 3.7.x driver. Use exactly 3.7.x. A 3.8.x driver
will fail with a `Could not locate method` error.
#### Python
1. Install the driver:
```bash
pip install 'gremlinpython>=3.7,<3.8'
```
2. Connect to AGS and run a traversal:
```python
from gremlin_python.process.anonymous_traversal import traversal
from gremlin_python.driver.driver_remote_connection import DriverRemoteConnection
g = traversal().with_remote(
DriverRemoteConnection("ws://localhost:8182/gremlin", "g")
)
# Write two vertices and an edge
alice = g.addV("person").property("name", "alice").next()
bob = g.addV("person").property("name", "bob").next()
g.add_e("knows").from_(alice).to(bob).property("since", 2020).iterate()
# Read them back
friends = g.V().has("person", "name", "alice").out("knows").values("name").to_list()
print(friends) # ['bob']
```
#### Java
1. Create a Maven project if you do not have one, then add the driver to your `pom.xml`:
```xml
org.apache.tinkerpopgremlin-driver3.7.3
```
2. Connect to AGS and run a traversal (imports omitted for brevity):
```java
Cluster cluster = Cluster.build("localhost").port(8182).create();
GraphTraversalSource g = traversal().withRemote(DriverRemoteConnection.using(cluster, "g"));
List