---
title: "Deploy ArangoDB"
description: "Graph database, document store, full-text search, one AQL query language"
category: "Other"
url: https://railway.com/deploy/arangodb
---

# Deploy ArangoDB

Graph database, document store, full-text search, one AQL query language

**[Deploy ArangoDB on Railway](https://railway.com/template/arangodb)**

Machine-readable deploy manifest (JSON, validated by TemplateCI): https://railway.com/deploy/arangodb/manifest.json

- **Creator:** A3A
- **Category:** Other

## Template content

### dbserver1 https://raw.githubusercontent.com/arangodb/arangodb/devel/js/apps/system/_admin/aardvark/APP/frontend/img/arango-icon.svg

- **Image:** arangodb:3.12
- **Start command:** `/bin/sh -c 'umask 077; printf %s "$ARANGO_JWT_SECRET" > /tmp/arangodb.jwt; mkdir -p "$ARANGO_DATA_DIR"; M=$(cat /sys/fs/cgroup/memory.max 2>/dev/null || echo max); case "$M" in ""|max) : ;; *) export ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY="$M";; esac; set -- $(cat /sys/fs/cgroup/cpu.max 2>/dev/null || echo max 1); case "$1" in ""|max) : ;; *) C=$(( $1 / $2 )); [ "$C" -lt 1 ] && C=1; export ARANGODB_OVERRIDE_DETECTED_NUMBER_OF_CORES="$C";; esac; exec /entrypoint.sh arangod --cluster.my-role PRIMARY --cluster.my-address "$ARANGO_MY_ADDRESS" --cluster.agency-endpoint "$AGENCY_EP1" --cluster.agency-endpoint "$AGENCY_EP2" --cluster.agency-endpoint "$AGENCY_EP3" --server.endpoint "tcp://[::]:$PORT" --server.jwt-secret-keyfile /tmp/arangodb.jwt --database.directory "$ARANGO_DATA_DIR"'`
- **Health check:** /_admin/server/availability

### gateway https://cdn.jsdelivr.net/gh/homarr-labs/dashboard-icons/svg/caddy.svg

- **Image:** caddy:2-alpine
- **Start command:** `/bin/sh -c 'printf %s "$CADDY_CONFIG" > /etc/caddy/config.json; caddy validate --config /etc/caddy/config.json || exit 1; exec caddy run --config /etc/caddy/config.json'`
- **Health check:** /healthz
- **Public domain:** Yes

### agent3 https://raw.githubusercontent.com/arangodb/arangodb/devel/js/apps/system/_admin/aardvark/APP/frontend/img/arango-icon.svg

- **Image:** arangodb:3.12
- **Start command:** `/bin/sh -c 'umask 077; printf %s "$ARANGO_JWT_SECRET" > /tmp/arangodb.jwt; mkdir -p "$ARANGO_DATA_DIR"; M=$(cat /sys/fs/cgroup/memory.max 2>/dev/null || echo max); case "$M" in ""|max) : ;; *) export ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY="$M";; esac; set -- $(cat /sys/fs/cgroup/cpu.max 2>/dev/null || echo max 1); case "$1" in ""|max) : ;; *) C=$(( $1 / $2 )); [ "$C" -lt 1 ] && C=1; export ARANGODB_OVERRIDE_DETECTED_NUMBER_OF_CORES="$C";; esac; exec /entrypoint.sh arangod --agency.activate true --agency.size 3 --agency.endpoint "$AGENCY_EP1" --agency.endpoint "$AGENCY_EP2" --agency.endpoint "$AGENCY_EP3" --agency.my-address "$ARANGO_MY_ADDRESS" --agency.supervision true --server.endpoint "tcp://[::]:$PORT" --server.jwt-secret-keyfile /tmp/arangodb.jwt --database.directory "$ARANGO_DATA_DIR"'`

### coordinator1 https://raw.githubusercontent.com/arangodb/arangodb/devel/js/apps/system/_admin/aardvark/APP/frontend/img/arango-icon.svg

- **Image:** arangodb:3.12
- **Start command:** `/bin/sh -c 'umask 077; printf %s "$ARANGO_JWT_SECRET" > /tmp/arangodb.jwt; mkdir -p "$ARANGO_DATA_DIR"; M=$(cat /sys/fs/cgroup/memory.max 2>/dev/null || echo max); case "$M" in ""|max) : ;; *) export ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY="$M";; esac; set -- $(cat /sys/fs/cgroup/cpu.max 2>/dev/null || echo max 1); case "$1" in ""|max) : ;; *) C=$(( $1 / $2 )); [ "$C" -lt 1 ] && C=1; export ARANGODB_OVERRIDE_DETECTED_NUMBER_OF_CORES="$C";; esac; exec /entrypoint.sh arangod --cluster.my-role COORDINATOR --cluster.my-address "$ARANGO_MY_ADDRESS" --cluster.agency-endpoint "$AGENCY_EP1" --cluster.agency-endpoint "$AGENCY_EP2" --cluster.agency-endpoint "$AGENCY_EP3" --server.endpoint "tcp://[::]:$PORT" --server.jwt-secret-keyfile /tmp/arangodb.jwt --database.directory "$ARANGO_DATA_DIR"'`
- **Health check:** /_admin/server/availability

### dbserver2 https://raw.githubusercontent.com/arangodb/arangodb/devel/js/apps/system/_admin/aardvark/APP/frontend/img/arango-icon.svg

- **Image:** arangodb:3.12
- **Start command:** `/bin/sh -c 'umask 077; printf %s "$ARANGO_JWT_SECRET" > /tmp/arangodb.jwt; mkdir -p "$ARANGO_DATA_DIR"; M=$(cat /sys/fs/cgroup/memory.max 2>/dev/null || echo max); case "$M" in ""|max) : ;; *) export ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY="$M";; esac; set -- $(cat /sys/fs/cgroup/cpu.max 2>/dev/null || echo max 1); case "$1" in ""|max) : ;; *) C=$(( $1 / $2 )); [ "$C" -lt 1 ] && C=1; export ARANGODB_OVERRIDE_DETECTED_NUMBER_OF_CORES="$C";; esac; exec /entrypoint.sh arangod --cluster.my-role PRIMARY --cluster.my-address "$ARANGO_MY_ADDRESS" --cluster.agency-endpoint "$AGENCY_EP1" --cluster.agency-endpoint "$AGENCY_EP2" --cluster.agency-endpoint "$AGENCY_EP3" --server.endpoint "tcp://[::]:$PORT" --server.jwt-secret-keyfile /tmp/arangodb.jwt --database.directory "$ARANGO_DATA_DIR"'`
- **Health check:** /_admin/server/availability

### agent2 https://raw.githubusercontent.com/arangodb/arangodb/devel/js/apps/system/_admin/aardvark/APP/frontend/img/arango-icon.svg

- **Image:** arangodb:3.12
- **Start command:** `/bin/sh -c 'umask 077; printf %s "$ARANGO_JWT_SECRET" > /tmp/arangodb.jwt; mkdir -p "$ARANGO_DATA_DIR"; M=$(cat /sys/fs/cgroup/memory.max 2>/dev/null || echo max); case "$M" in ""|max) : ;; *) export ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY="$M";; esac; set -- $(cat /sys/fs/cgroup/cpu.max 2>/dev/null || echo max 1); case "$1" in ""|max) : ;; *) C=$(( $1 / $2 )); [ "$C" -lt 1 ] && C=1; export ARANGODB_OVERRIDE_DETECTED_NUMBER_OF_CORES="$C";; esac; exec /entrypoint.sh arangod --agency.activate true --agency.size 3 --agency.endpoint "$AGENCY_EP1" --agency.endpoint "$AGENCY_EP2" --agency.endpoint "$AGENCY_EP3" --agency.my-address "$ARANGO_MY_ADDRESS" --agency.supervision true --server.endpoint "tcp://[::]:$PORT" --server.jwt-secret-keyfile /tmp/arangodb.jwt --database.directory "$ARANGO_DATA_DIR"'`

### coordinator2 https://raw.githubusercontent.com/arangodb/arangodb/devel/js/apps/system/_admin/aardvark/APP/frontend/img/arango-icon.svg

- **Image:** arangodb:3.12
- **Start command:** `/bin/sh -c 'umask 077; printf %s "$ARANGO_JWT_SECRET" > /tmp/arangodb.jwt; mkdir -p "$ARANGO_DATA_DIR"; M=$(cat /sys/fs/cgroup/memory.max 2>/dev/null || echo max); case "$M" in ""|max) : ;; *) export ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY="$M";; esac; set -- $(cat /sys/fs/cgroup/cpu.max 2>/dev/null || echo max 1); case "$1" in ""|max) : ;; *) C=$(( $1 / $2 )); [ "$C" -lt 1 ] && C=1; export ARANGODB_OVERRIDE_DETECTED_NUMBER_OF_CORES="$C";; esac; exec /entrypoint.sh arangod --cluster.my-role COORDINATOR --cluster.my-address "$ARANGO_MY_ADDRESS" --cluster.agency-endpoint "$AGENCY_EP1" --cluster.agency-endpoint "$AGENCY_EP2" --cluster.agency-endpoint "$AGENCY_EP3" --server.endpoint "tcp://[::]:$PORT" --server.jwt-secret-keyfile /tmp/arangodb.jwt --database.directory "$ARANGO_DATA_DIR"'`
- **Health check:** /_admin/server/availability

### agent1 https://raw.githubusercontent.com/arangodb/arangodb/devel/js/apps/system/_admin/aardvark/APP/frontend/img/arango-icon.svg

- **Image:** arangodb:3.12
- **Start command:** `/bin/sh -c 'umask 077; printf %s "$ARANGO_JWT_SECRET" > /tmp/arangodb.jwt; mkdir -p "$ARANGO_DATA_DIR"; M=$(cat /sys/fs/cgroup/memory.max 2>/dev/null || echo max); case "$M" in ""|max) : ;; *) export ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY="$M";; esac; set -- $(cat /sys/fs/cgroup/cpu.max 2>/dev/null || echo max 1); case "$1" in ""|max) : ;; *) C=$(( $1 / $2 )); [ "$C" -lt 1 ] && C=1; export ARANGODB_OVERRIDE_DETECTED_NUMBER_OF_CORES="$C";; esac; exec /entrypoint.sh arangod --agency.activate true --agency.size 3 --agency.endpoint "$AGENCY_EP1" --agency.endpoint "$AGENCY_EP2" --agency.endpoint "$AGENCY_EP3" --agency.my-address "$ARANGO_MY_ADDRESS" --agency.supervision true --server.endpoint "tcp://[::]:$PORT" --server.jwt-secret-keyfile /tmp/arangodb.jwt --database.directory "$ARANGO_DATA_DIR"'`

## Documentation

# Deploy and Host ArangoDB on Railway

ArangoDB is a multi-model database: documents, graphs and key-value pairs live in one storage engine, queried with one language, AQL. A single query can filter JSON documents, walk a graph several hops deep and join the two results — work that otherwise needs a document store and a separate graph database wired together in application code. Teams use it for knowledge graphs, recommendation engines, fraud detection and permission models.

This template lets you deploy ArangoDB on Railway as a real cluster, not a single container. Eight services come up pre-wired: `agent1`, `agent2` and `agent3` form the RAFT agency holding cluster configuration, `dbserver1` and `dbserver2` store the shards and replicate to each other, `coordinator1` and `coordinator2` answer AQL queries and serve the web interface, and a Caddy `gateway` puts one public HTTPS URL in front of both coordinators. Each ArangoDB service has its own volume; only the gateway is reachable from the internet, and it needs authentication.

![Diagram of the ArangoDB cluster services on Railway](https://res.cloudinary.com/rroe4rtk/image/upload/v1788848802/arangodb-architecture.png)

## Getting Started with ArangoDB on Railway

Deploying creates the whole cluster at once: the agency elects a leader, the DB-Servers register with it, then the first coordinator bootstraps the system collections. Expect a minute or two before the public URL answers. The gateway domain serves the ArangoDB web interface login. Sign in as `root` with the password from `ARANGODB_DEFAULT_ROOT_PASSWORD`, readable on the `coordinator1` service. The database applies it during bootstrap, so `root` never exists without a password and there is no shipped default to change.

After login you pick a database; start with `_system`. Open **Nodes** to confirm the cluster is whole — two Coordinators, two DB-Servers and three Agents, all green, one agent leading. Then create a database from **Databases**, add a collection, and run AQL under **Queries**. A good first check is a small edge collection and a named graph under **Graphs**, then a traversal: that exercises a coordinator, both DB-Servers and the agency in one request. Add users under **Users** before pointing an app at the cluster.

![ArangoDB Nodes view listing two Coordinators, two DB-Servers and three Agents](https://res.cloudinary.com/rroe4rtk/image/upload/v1788848804/arangodb-cluster-nodes.png)
![ArangoDB graph viewer drawing the flight_network airport routes](https://res.cloudinary.com/rroe4rtk/image/upload/v1788848805/arangodb-graph-viewer.png)
![AQL graph traversal returning reachable airports with hop counts](https://res.cloudinary.com/rroe4rtk/image/upload/v1788848807/arangodb-aql-traversal.png)

## About Hosting ArangoDB

Self-hosting ArangoDB makes sense when your data is graph-shaped but your workload is not purely graph — a catalogue with recommendation edges, permissions layered over user documents, a supply chain where both parts and routes are queried. It also keeps the data in your own infrastructure.

Key capabilities:

- **AQL**, one declarative language across documents, graphs and key-value access, with joins and multi-hop traversals in a single statement
- **Named graphs** with a visual browser, shortest-path, k-paths and pattern matching
- **ArangoSearch**, full-text search and BM25/TF-IDF ranking in the same engine
- **Sharding** with synchronous replication and automatic failover
- Official drivers for JavaScript, Java, Python, Go, PHP, Rust and .NET

The cluster splits into three roles. The **agency** is a small RAFT-replicated store holding the cluster plan — which shard lives where, which server is healthy. Three agents give it a quorum, so one can be redeployed without stopping writes. **DB-Servers** hold the shards; at a replication factor of two every shard has a leader on one and a follower on the other, and a failure promotes the follower. **Coordinators** hold no data — they parse AQL, fan work to the DB-Servers and merge results, so two behind the gateway spread load and survive a redeploy.

## Why Deploy ArangoDB on Railway

Railway handles the parts of a database cluster that are usually manual work:

- Private networking between all seven ArangoDB services, no ports exposed publicly
- A persistent volume per node, so shards and the agency survive restarts
- One managed HTTPS domain on the gateway, certificates included
- Health checks on the coordinators and DB-Servers, plus automatic restarts

## Common Use Cases

- **Knowledge graphs and RAG backends** — keep documents and the relationships between entities in one place, then traverse from a match to its neighbours
- **Recommendation engines** — model users, items and interactions as a graph and answer "customers who bought this also bought" in a few lines of AQL
- **Fraud and risk analysis** — find rings of related accounts by walking shared devices, addresses or payment methods several hops out from a suspect record

## Dependencies for ArangoDB

- `arangodb:3.12` — the official image, used by all seven cluster services. Each one's role is set by its start command.
- `caddy:2-alpine` — the `gateway`, load balancing across both coordinators and serving `/healthz`.

### Environment Variables Reference

| Variable | Service | Purpose |
|---|---|---|
| `ARANGODB_DEFAULT_ROOT_PASSWORD` | coordinator1, coordinator2 | Password for `root`, applied at cluster bootstrap |
| `ARANGO_JWT_SECRET` | all ArangoDB services | Shared secret nodes authenticate to each other with |
| `ARANGO_MY_ADDRESS` | all ArangoDB services | Address this node advertises to the cluster |
| `CADDY_CONFIG` | gateway | Load balancer configuration in Caddy JSON |

### Deployment Dependencies

- Source: [github.com/arangodb/arangodb](https://github.com/arangodb/arangodb)
- Image: [hub.docker.com/_/arangodb](https://hub.docker.com/_/arangodb)
- Documentation: [docs.arangodb.com](https://docs.arangodb.com)

## Hardware Requirements for Self-Hosting ArangoDB

Per service. Agents and coordinators are light; DB-Servers hold the data.

| Resource | Minimum | Recommended |
|---|---|---|
| CPU | 1 vCPU agents, 2 vCPU DB-Servers | 2–4 vCPU per node |
| RAM | 512 MB agents, 2 GB DB-Servers | 1 GB agents, 4–8 GB DB-Servers |
| Storage | 1 GB agents, 5 GB DB-Servers | Sized to the dataset plus replicas |
| Runtime | Docker, x86-64 or ARM64 | — |

ArangoDB sizes its caches and query memory limits from the machine it detects, so in a container it must be told the real limit. This template reads that from the cgroup at startup and passes it through `ARANGODB_OVERRIDE_DETECTED_TOTAL_MEMORY` and `ARANGODB_OVERRIDE_DETECTED_NUMBER_OF_CORES`, so resizing a service retunes it.

## Self-Hosting ArangoDB with Docker

A single node is enough to try AQL locally. This starts one on port 8529:

```
docker run -d --name arangodb -p 8529:8529 \
  -e ARANGO_ROOT_PASSWORD=changeme \
  -v arangodb_data:/var/lib/arangodb3 \
  arangodb:3.12
```

Open `http://localhost:8529` and sign in as `root`. In the cluster shape this template deploys, each process takes its role from flags. An agent looks like this:

```
arangod --agency.activate true --agency.size 3 \
  --agency.endpoint tcp://agent1:8531 \
  --agency.endpoint tcp://agent2:8531 \
  --agency.endpoint tcp://agent3:8531 \
  --agency.my-address tcp://agent1:8531 \
  --server.endpoint tcp://[::]:8531 \
  --server.jwt-secret-keyfile /secrets/jwt \
  --database.directory /var/lib/arangodb3/agent
```

DB-Servers and coordinators take `--cluster.my-role PRIMARY` or `COORDINATOR`, with `--cluster.agency-endpoint` pointing at the same three agents.

## Is ArangoDB Free to Self-Host?

ArangoDB is source-available. Version 3.12 ships under the Business Source License 1.1, and the prepackaged builds fall under the ArangoDB Community License: free for internal production use, clusters included, capped at a 100 GiB dataset and three clusters. Offering ArangoDB itself as a service needs a commercial licence, and from 3.12.5 the community build carries the full Enterprise feature set. There is no licence fee for this template — on Railway you pay for the compute, memory and storage the eight services use.

## FAQ

**What is ArangoDB?**
A source-available, multi-model database storing documents, graphs and key-value data in one engine, queried with AQL, its declarative query language.

**What does this Railway template deploy?**
A complete ArangoDB cluster: a three-node agency, two DB-Servers with synchronous replication, two coordinators, and a Caddy gateway load balancing the public HTTPS URL across both.

**Why does the template include three agent services?**
The agency is RAFT-based and needs an odd number of members to hold a majority. Three lets one be redeployed while the cluster keeps accepting writes; a single agent makes every restart an outage.

**Why are there two DB-Servers instead of one?**
ArangoDB creates its system collections with a replication factor of two, so a second DB-Server is required for the cluster to finish bootstrapping. It also gives every shard a follower, so losing a node loses no data.

**How do I connect an application to self-hosted ArangoDB?**
Point any official driver at the gateway's HTTPS domain with the `root` credentials, or a user you create in the web interface. From another Railway service in the same project, use `coordinator1.railway.internal:8529` to keep traffic off the public internet.

**How do I add more capacity to self-hosted ArangoDB?**
Raise CPU, memory or volume size on the DB-Servers from the Railway dashboard. To add a DB-Server, duplicate one with the same variables and a new `ARANGO_MY_ADDRESS`; it registers with the agency at startup and ArangoDB rebalances shards onto it.


## Similar templates

- [Rocky Linux](https://railway.com/deploy/rocky-linux) — Hosted Rocky Linux 9 workspace with SSH and persistent storage. 🚀
- [Foundry Virtual Tabletop](https://railway.com/deploy/X5tR6G) — A Self-Hosted & Modern Roleplaying Platform
- [Letta Code Remote](https://railway.com/deploy/letta-code-remote) — Run a Letta Code agent 24/7. No inbound ports, just deploy.

Open this page in a browser: https://railway.com/deploy/arangodb
