Skip to content

This is the multi-page printable view of this section. .

Return to the regular view of this page.

HugeGraph (OLTP)

This section covers the HugeGraph Server standalone quick start and the PD and Store guides needed for distributed deployments.

See the DeepWiki project overview. For installation, configuration, and runtime behavior, use the documentation and code for the relevant HugeGraph version.

Start with the Server standalone quick start, which distinguishes ASF 1.7.0 release packages from builds of master. HStore deployments also require PD and Store.

GitHub Access: https://github.com/apache/hugegraph

1 - HugeGraph Server Quick Start

1 HugeGraph Server Overview

apache/hugegraph is the main repository for the HugeGraph graph database. Its top-level modules include hugegraph-server, hugegraph-pd, and hugegraph-store. This page describes the hugegraph-server module and the service it runs.

The hugegraph-server module contains hugegraph-core, hugegraph-api, hugegraph-dist, and storage adapters. Core implements the property graph model, transactions, and TinkerPop interfaces. API provides the HTTP service and delegates client requests to Core. Graph data is stored in RocksDB (the default standalone backend), HStore (distributed), or HBase.

Warning

Version scope: This guide distinguishes between official releases and the development master branch. For official installations, use official release archives (such as 1.7.0 or the upcoming 1.8.0). Source builds, default configurations, and startup behaviors follow the apache/hugegraph master branch (currently targeting 1.8.0). A master build is not an ASF release artifact, even if its version number matches a release. Supported storage backends include RocksDB, HStore, and HBase; see 1.5.x documentation for deprecated legacy backends.

Naming: HugeGraph means the overall project or main repository, hugegraph-server is its Server module, and HugeGraphServer is the Java service class. Server below means the running graph database service.

flowchart TD
    A{Choose installation source}
    A -->|Release| R["HugeGraph 1.7.0 archive"]
    R --> V[Verify SHA-512]
    V --> X[Extract and use bundled configuration]
    A -->|Development| M["master source"]
    M --> B["mvn package -DskipTests"]
    B --> C[Check RocksDB configuration in conf/graphs]
    C --> I[bin/init-store.sh]
    I --> S["bin/start-hugegraph.sh -p true"]
    S --> Q["Request /versions and graph vertices"]

The map uses short labels for the repository modules described above. server, core, api, dist, pd, and store refer to the corresponding hugegraph- modules; dist packages the distribution.

---
markmap:
  spacingHorizontal: 40
---
# HugeGraph
## server
- core
- api
- dist
## pd
## store

2 Dependency for Building/Running

2.1 Install Java 17 (JDK 17)

Starting with HugeGraph 1.8.0, use Java 17; 1.7.0 is the last release supporting Java 11. Build all modules with JDK 17 and Maven 3.6.3 or later, and run Server, PD and Store with JDK 17. Server security check (-s true) requires Java 17 to 23 and a readable conf/java-security.properties; on Java 24 or later, start Server with -s false (JDK 24+ dropped Security Manager via JEP 486).

Before continuing, run java -version to confirm your JDK version.

Note

TinkerPop 3.8.1 Compatibility & Key Changes

HugeGraph 1.8.0 upgrades to TinkerPop 3.8.1 and Groovy 4.0.25. Use the Gremlin configuration files bundled with Server.

  • Serializer Packages: Driver serializer classes moved from org.apache.tinkerpop.gremlin.driver.ser to org.apache.tinkerpop.gremlin.util.ser. Keep HugeGraph registries.
  • Graph.Features: supportsUniformListValues() returns false for properties. Schema valueList()/LIST properties remain supported without rewriting existing data.
  • Traversal Multiplicity: Mid-traversal scans retain input multiplicity (e.g. for 3 vertices, g.V().V().count() returns 9L).
  • Date & Time Types: DATE properties accept OffsetDateTime for writes and indexed equality/range queries (instant normalized to milliseconds).
  • Filtering Behavior: P.typeOf() runs as a local filter; count filtering applies range optimizations only when predicate branches are provably safe.
GraphBinary (Recommended)
1# Bundled Driver and Console default to GraphBinary V1
2# - Schema results are standard maps
3# - Blob values are binary (including inside returned elements)
4serializer:
5  className: org.apache.tinkerpop.gremlin.util.ser.GraphBinaryMessageSerializerV1
6  config:
7    builder: org.apache.hugegraph.io.HugeGraphTypeSerializerRegistryBuilder
8    ioRegistries: [org.apache.hugegraph.io.HugeGraphIoRegistry]
GraphSON (HTTP / Legacy)
1# Default HTTP JSON uses untyped GraphSON V1
2# - Preserves the legacy Tree key/value array structure
3# - Typed GraphSON V1 is disabled for security (typed V2/V3 remain available for simple values and IDs)
4# - graph.schema() returns property keys, vertex labels, edge labels, and index labels
Tip

For complete Gremlin syntax rewrites, compatibility requirements, and reference tables, see the 1.8 Gremlin & TinkerPop Migration Guide. Additional runtime details are in the server runtime documentation.

3 Deploy

There are four ways to deploy the Server service:

Warning

Production requires authentication and restricted network access

HugeGraph disables user authentication by default. Enable authentication and authorization, maintain an IP allowlist, and grant minimum permissions. Do not expose Gremlin, Cypher, or other query APIs directly to the public Internet. Retain Server audit-*.log and restrict read access. auth.audit_log_rate limits per-user output rate rather than turning audit logging on or off. See the security guide.

3.1 Use Docker container (Convenient for Test/Dev)

For complete container setup instructions, refer to the Docker deployment guide.

Run a standalone Server container with the RocksDB backend:

Quick Start (Default)
1docker run -itd --name=server -p 8080:8080 hugegraph/hugegraph:1.7.0
With Sample Graph
1# Preload the built-in sample graph at startup
2docker run -itd --name=server -p 8080:8080 -e PRELOAD="true" hugegraph/hugegraph:1.7.0
With Authentication
1# Enable authentication mode and set the admin password
2docker run -itd --name=server -p 8080:8080 -e PASSWORD="replace-with-your-password" hugegraph/hugegraph:1.7.0

Common container inspection operations:

  • Inspect container shell: docker exec -it server bash
  • Check startup logs: docker logs -f server
  • Verify service health: curl -fsS http://127.0.0.1:8080/versions

If you use Docker Desktop, you can set the options as follows:

Docker Desktop settings for a HugeGraph container
Note

The Docker Compose files use bridge networking (hg-net) and work on Linux and Mac (Docker Desktop). For the 3-node distributed cluster on Mac (Docker Desktop), allocate at least 12 GB of memory (Settings → Resources → Memory). On Linux, Docker uses host memory directly.

Use docker compose to manage multiple HugeGraph services from one configuration. Four Compose files are available in the docker/ directory:

TopologyCompose fileServices
Standalone (start here)docker-compose.yml1 RocksDB Server + 1 Hubble
Minimal HStore (current master)docker-compose-hstore.yml1 PD + 1 Store + 1 Server + 1 Hubble; locally built master images required
HA reference (current master)docker-compose-3pd-3store-3server.yml3 PD + 3 Store + 3 Server + 1 Hubble; locally built master images required
Source build override for the minimal HStore topologydocker-compose.dev.yml(used together with docker-compose-hstore.yml)
1cd hugegraph/docker
2# Keep the version aligned with the latest release, for example 1.x.0
3HUGEGRAPH_VERSION=1.7.0 docker compose -f docker-compose.yml up -d --wait

The standalone topology publishes the Server on port 8080 and Hubble on 127.0.0.1:8088. HUGEGRAPH_VERSION selects the Server, PD, and Store image tags; Hubble is selected separately with HUBBLE_IMAGE.

The standalone docker-compose.yml example uses hugegraph/hugegraph:1.7.0; its docker/conf/hubble/standalone.properties is bundled in source. Compose reads the administrator password from HUGEGRAPH_ADMIN_PASSWORD and JWT secret from HUGEGRAPH_AUTH_TOKEN_SECRET, normally in docker/.env. A nonempty password enables authentication, automatically detected by Hubble. With docker run, use -e PASSWORD=xxx. Master HStore Compose files cannot be combined with 1.7.0 PD/Store/Server release images.

JWT version differences: Master-built Server maps HUGEGRAPH_AUTH_TOKEN_SECRET to HG_SERVER_AUTH_TOKEN_SECRET and writes startup configuration; preserve the secret across recreation. The 1.7.0 entrypoint handles older variables such as PASSWORD, ignoring HG_SERVER_AUTH_TOKEN_SECRET. To keep a stable JWT secret in 1.7.0, persist auth.token_secret in that version’s conf/graphs/hugegraph.properties. With a randomly generated default, do not assume issued JWTs survive Server restarts.

See docker/README.md for the full setup guide.

Server service identity with PD

For a PD-backed Server, the Helm chart exposes server.serviceId and server.graphSpace. Both default to DEFAULT, which preserves the existing server.service_id and server.graphspace values in conf/rest-server.properties. A non-default chart value injects HG_SERVER_SERVICE_ID or HG_SERVER_GRAPHSPACE into the Server container. These service identity chart settings (server.serviceId, server.graphSpace, and server.testGraphAlias) apply to development 1.8.0+ builds and charts; older versions such as 1.7.0 do not support these options. Do not use this example with older chart or image versions lacking these features. Non-empty service IDs supplied through HG_SERVER_SERVICE_ID, SERVICE_ID, or server.serviceId must use printable ASCII; spaces and backslashes are supported, while deployment checks reject non-ASCII and control characters. This entrypoint restriction does not change Core Service naming or existing manually supplied properties. Helm preserves dollar signs in server.serviceId literally, including $(POD_IP); this field does not expand Kubernetes environment references. The full service ID, including / and -, is retained when service metadata is reloaded or its graph space is cleared. Set the identity through these chart values; Server extraEnv reserves both the new and legacy identity variable names. HG_SERVER_GRAPHSPACE, the effective GRAPH_SPACE fallback, and server.graphSpace accept DEFAULT or an existing space name of up to 48 lowercase letters, digits, and underscores, starting with a letter:

1helm upgrade --install hg ./helm/hugegraph \
2  --set-string server.serviceId=analytics \
3  --set-string server.graphSpace=team_a

Before deploying Servers assigned to team_a, create that graph space through an existing Server in DEFAULT, using an account with permission to create graph spaces. The chart and these environment variables do not create graph spaces; all replicas in the Server Deployment use the same identity.

To check a graph in that space with helm test, first create the target graph and set --set-string server.testGraphAlias=team_a-demo to its actual Gremlin binding. Creating the graph space does not create a hugegraph graph.

For container deployments, HG_SERVER_SERVICE_ID and HG_SERVER_GRAPHSPACE write the same two properties. The legacy SERVICE_ID and GRAPH_SPACE names remain accepted: a non-empty new variable wins over its legacy counterpart. If both names for a property are unset or empty, its existing value is preserved. Compose does not automatically forward these host variables; add explicit Server environment: entries in a Compose override. See the Helm chart documentation for details.

These settings select the Server’s PD service metadata. They do not move existing graphs or change server.path_graphspace for REST paths that omit the graph space. Use /graphspaces/team_a/... paths and select the matching graph space and service in Hubble. When authentication is enabled, explicit paths still require authorization.

server.testGraphAlias defaults to DEFAULT-hugegraph. The hook checks this existing local binding on every Server Pod; it does not derive the alias from server.graphSpace. A local binding may exist independently of the Server’s assigned PD graph space, so a successful default hook does not validate graphs in team_a. If Could not rebind appears, first check that the requested graph exists and that its alias is correct. A Pod restart cannot create a missing graph or correct an alias. Match the binding’s case: a local Demo.properties can bind DEFAULT-Demo, while REST-created graph names are lowercase.

Configuration rendering and entrypoint checks alone do not establish non-default Linux discovery, authentication, or isolation between graph spaces.

Note
  1. HugeGraph Docker images are provided as a convenient way to start HugeGraph quickly, but they are not official ASF distribution artifacts. You can find more details in the ASF Release Distribution Policy.

  2. We recommend using a release tag (such as 1.7.0 or 1.x.0) for stable deployments. Use the latest tag only if you want the newest features still under development.

3.2 Download a Released Archive

This example uses HugeGraph 1.7.0. For other versions, confirm the release and filenames in the ASF download directory. A master source build is not a released binary.

1cd /path/to/downloads
2wget https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-incubating-1.7.0.tar.gz
3wget https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-incubating-1.7.0.tar.gz.sha512
4sha512sum -c apache-hugegraph-incubating-1.7.0.tar.gz.sha512
5tar zxf apache-hugegraph-incubating-1.7.0.tar.gz

Extract only after SHA-512 verification succeeds. You can also verify the PGP signature following Apache release procedures:

1wget https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-incubating-1.7.0.tar.gz.asc
2wget https://downloads.apache.org/hugegraph/KEYS
3gpg --import KEYS
4gpg --verify apache-hugegraph-incubating-1.7.0.tar.gz.asc apache-hugegraph-incubating-1.7.0.tar.gz

Trust publisher keys only after verifying them through Apache project channels. Signature verification can complement SHA-512 checks.

3.3 Build from master Source

These commands build the development branch, not the 1.7.0 release.

Install wget or curl before building.

Download HugeGraph source:

1git clone --branch master https://github.com/apache/hugegraph.git

Compile and package:

1cd hugegraph
2# (Optional) use "-P stage" param if you build failed with the latest code(during pre-release period)
3mvn package -DskipTests -ntp

A successful build logs:

1[INFO] BUILD SUCCESS

The build creates an aggregate master archive under repository-root target/ (the current source version property is 1.8.0):

1target/apache-hugegraph-1.8.0.tar.gz

The filename version comes from source revision; it does not make the build an ASF release artifact. The build also creates repository-root apache-hugegraph-1.8.0/, containing a Server directory named by that module’s final.name, currently apache-hugegraph-server-1.8.0. If retaining only the archive, first run tar zxf target/apache-hugegraph-1.8.0.tar.gz, then enter the Server directory.

Default builds bundle rocksdb, hbase, and hstore modules, listed in backends within backend.properties in the hugegraph-dist JAR. For a RocksDB-only distribution, add -Drocksdb-only:

1mvn package -DskipTests -ntp -Drocksdb-only
Outdated tools

3.4 One-click deployment (Outdated)

Outdated This status applies only to this one-click deployment entry.

HugeGraph-Tools provides a one-click deployment command that downloads, extracts, configures, and starts the Server service and HugeGraph-Hubble. These tools are included in the HugeGraph-Toolchain distribution.

Of course, you should download the tarball of HugeGraph-Toolchain first.

1# download toolchain binary package, it includes loader + tool + hubble
2# please check the latest version (e.g. here is 1.7.0)
3wget https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-toolchain-incubating-1.7.0.tar.gz
4tar zxf *hugegraph-*.tar.gz
5
6# enter the tool's package
7cd *hugegraph*/*tool* 

note: ${version} is the version, The latest version can refer to Download Page, or click the link to download directly from the Download page

The general entry script for HugeGraph-Tools is bin/hugegraph, Users can use the help command to view its usage, here only the commands for one-click deployment are introduced.

1bin/hugegraph deploy -v {hugegraph-version} -p {install-path} [-u {download-path-prefix}]

{hugegraph-version} is the Server service and HugeGraphStudio version; see conf/version-mapping.yaml for supported mappings. {install-path} is the installation directory, while {download-path-prefix} optionally overrides the tarball download location. For example, deploy version 0.6 with bin/hugegraph deploy -v 0.6 -p services.

4 Configuration

Server archives include conf/rest-server.properties, conf/gremlin-server.yaml, and conf/graphs/hugegraph.properties; source builds assemble them from hugegraph-server/hugegraph-dist/src/assembly/static/conf/. Edit them inside the extracted Server directory without a separate generation step. Defaults vary by release; the following defaults and startup behavior describe master.

For standalone RocksDB, confirm backend=rocksdb and serializer=binary in conf/graphs/hugegraph.properties. Normal Server initialization scans conf/graphs/ and loads local graphs without requiring graph.load_from_local_config=true. This option defaults to false and controls constructor preloading. Restart Server to apply graph configuration changes; do not use hot reload for maintenance.

See the configuration guide and option reference for details.

5 Startup

5.1 Use a startup script to startup

Startup is divided into “first startup” and “non-first startup”. On the first startup, you need to initialize the backend database before starting the service.

If the service was stopped manually, or needs to be started again for any other reason, you can usually start it directly because the backend database is persistent.

When HugeGraphServer starts, it connects to the backend storage and checks its version information. If the backend has not been initialized, or if it was initialized with an incompatible version (for example, old-version data), HugeGraphServer will fail to start and report an error.

If you need to access HugeGraphServer externally, modify the restserver.url configuration item in rest-server.properties (the default is http://127.0.0.1:8080) and change it to the machine name or IP address.

Since the configuration (hugegraph.properties) and startup steps required by various backends are slightly different, the following will introduce the configuration and startup of each backend one by one.

Warning

Configure authentication before production startup

Enable Server authentication and authorization with a strong, nondefault administrator password, an IP allowlist, and minimum business-user permissions.

5.1.1 Distributed Storage (HStore)

First deploy PD and Store; see the PD Quick Start and Store Quick Start.

Warning

umask 077 protects the new .env, but set-hubble-pd-password.sh sets generated .local.properties permissions to 0644, making the PD secret readable by other local users. This example assumes trusted local users. On shared hosts, set ownership and read permissions for the Hubble runtime user so Hubble can read the files while unauthorized users cannot. Keeping files untracked does not replace file permission controls.

Distributed storage configuration and startup

Distributed storage, introduced after HugeGraph 1.5.0, uses HugeGraph-PD and HugeGraph-Store for distributed data storage and computing.

After PD and Store are running:

  1. Edit Server hugegraph.properties:
1backend=hstore
2serializer=binary
3
4# PD RPC addresses, separated by commas
5pd.peers=127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688
6pd.cluster=hg
 1# Simple example with authentication
 2gremlin.graph=org.apache.hugegraph.auth.HugeFactoryAuthProxy
 3
 4# Required HStore backend
 5backend=hstore
 6serializer=binary
 7store=hugegraph
 8
 9# pd config
10pd.peers=127.0.0.1:8686
11pd.cluster=hg

The distribution includes conf/graphs/hstore.properties.template; copy it over conf/graphs/hugegraph.properties and adjust pd.peers.

This example uses cluster=hg in rest-server.properties and pd.cluster=hg in graph configuration, matching the master Compose cluster below. These are separate keys for the Server process and graph respectively, not one setting. Select an appropriate cluster name. Likewise, pd.peers in each file has its own configuration scope; this example supplies the same PD RPC addresses to both.

The backend selects the task scheduler: HStore uses distributed scheduling; others use local scheduling. task.scheduler_type is unnecessary and is ignored with a warning when retained for compatibility.

  1. Edit Server rest-server.properties:
1usePD=true
2# Use cluster hg, matching pd.cluster in graph configuration
3cluster=hg
4# Server process PD addresses; replace with actual PD RPC addresses
5pd.peers=127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688
6
7# Optional in local tests; authentication is mandatory in production
8# auth.authenticator=org.apache.hugegraph.auth.StandardAuthenticator

These addresses support multiple Server processes on one machine; 127.0.0.1 is local only. Across hosts, use routable IPs or DNS for restserver.url, gremlinserver.url, pd.peers, Gremlin host, and rpc.server_host. Advertised RPC addresses and ports must be mutually reachable.

For multiple Servers, edit each node’s rest-server.properties:

Node 1 (master):

 1usePD=true
 2restserver.url=http://127.0.0.1:8081
 3gremlinserver.url=http://127.0.0.1:8181
 4pd.peers=127.0.0.1:8686
 5
 6rpc.server_host=127.0.0.1
 7rpc.server_port=8091
 8
 9server.id=server-1
10server.role=master

Node 2 (worker):

 1usePD=true
 2restserver.url=http://127.0.0.1:8082
 3gremlinserver.url=http://127.0.0.1:8182
 4pd.peers=127.0.0.1:8686
 5
 6rpc.server_host=127.0.0.1
 7rpc.server_port=8092
 8
 9server.id=server-2
10server.role=worker

Also configure each node’s gremlin-server.yaml ports:

Node 1:

1host: 127.0.0.1
2port: 8181

Node 2:

1host: 127.0.0.1
2port: 8182

Start Server:

1bin/start-hugegraph.sh

Distributed startup order:

  1. Start HugeGraph-PD
  2. Start HugeGraph-Store
  3. Start Server

PD and Store manage HStore metadata and storage, so init-store skips that backend. With authentication enabled, init-store still creates the built-in admin account. If storage already holds this account, set init_store.enabled=false in rest-server.properties to skip the entire step, as Docker HStore topologies do.

Verify startup:

1curl http://localhost:8081/graphspaces/DEFAULT/graphs
2# Expected: {"graphs":["hugegraph"]}

Stop in reverse order:

  1. Stop Server
  2. Stop HugeGraph-Store
  3. Stop HugeGraph-PD
1bin/stop-hugegraph.sh
Docker HStore HA Cluster (Current Master)

docker-compose-3pd-3store-3server.yml uses master HG_PD_*, HG_STORE_*, and HG_SERVER_* variables unsupported by 1.7.0 release images. Build PD, Store, and Server from the same master source, all tagged local:

1# Run from the HugeGraph repository root
2docker build -f hugegraph-pd/Dockerfile -t hugegraph/pd:local .
3docker build -f hugegraph-store/Dockerfile -t hugegraph/store:local .
4docker build -f hugegraph-server/Dockerfile-hstore -t hugegraph/server:local .
5
6cd docker

Create the authentication environment in docker/ and generate HStore Hubble configuration. Replace the example administrator password; because .env uses single quotes, the password must contain neither single quotes nor newlines. The script generates random JWT and PD secrets and writes the PD secret to two untracked .local.properties files mounted by HStore Compose:

 1(
 2  set -eu
 3  command -v openssl >/dev/null
 4  jwt_secret="$(openssl rand -hex 32)"
 5  pd_secret="$(openssl rand -hex 24)"
 6  umask 077
 7  test ! -e .env || {
 8    echo ".env already exists; edit it instead of overwriting it" >&2
 9    exit 1
10  }
11  printf "HUGEGRAPH_ADMIN_PASSWORD='%s'\nHUGEGRAPH_AUTH_TOKEN_SECRET='%s'\nHG_PD_AUTH_SECRET_KEY='%s'\n" \
12    'replace-with-your-password' "${jwt_secret}" "${pd_secret}" > .env
13  HG_PD_AUTH_SECRET_KEY="${pd_secret}" ./set-hubble-pd-password.sh hstore
14  HG_PD_AUTH_SECRET_KEY="${pd_secret}" ./set-hubble-pd-password.sh hstore-ha
15)

Start HA from docker/. HUGEGRAPH_VERSION=local selects the locally built PD, Store, and Server images; Compose pull_policy: missing uses existing local tags first. HUBBLE_IMAGE still selects Hubble independently:

1set -a
2. ./.env
3set +a
4HUGEGRAPH_VERSION=local docker compose \
5  -f docker-compose-3pd-3store-3server.yml \
6  up -d --wait pd0 pd1 pd2 store0 store1 store2 server0 server1 server2 hubble

Generate HG_PD_AUTH_SECRET_KEY once for new data directories and reuse it on restart or when retaining data. Do not commit .env or generated conf/hubble/*.local.properties. Services communicate through container hostnames on the hg-net bridge. Server replicas need the shared JWT secret as well as the administrator password; set HUGEGRAPH_AUTH_TOKEN_SECRET. See the Docker cluster guide and docker/README.md for all variables.

Verify the cluster:

1curl -fsS http://localhost:8080/versions
2curl -fsS -u "hg:${HG_PD_AUTH_SECRET_KEY:?Load .env first}" \
3  http://localhost:8620/v1/stores

Master PD /v1/stores requires Basic authentication; this uses the generated, loaded HG_PD_AUTH_SECRET_KEY as the hg password.

Inspect runtime logs with docker logs <container-name>, such as docker logs hg-pd0.

See docker/README.md for variables, ports, and troubleshooting.

5.1.2 RocksDB / ToplingDB

The minimal standalone flow below uses a master build and preloads sample data to verify graph reads and writes.

  1. Check Java against the master build requirements.
  2. Build master source; the commands below use its nested Server directory.
  3. Confirm RocksDB configuration, then enter the build output’s nested Server directory.
  4. Initialize storage, then start the service with sample data using the commands below.
  5. Request /versions and sample graph vertices, and check the actual response contents.
Note

RocksDB is embedded and needs no separate deployment. GCC ≥ 4.3.0 (GLIBCXX_3.4.10) is required; upgrade first if needed.

Master conf/graphs/hugegraph.properties already sets backend=rocksdb and serializer=binary. Keep the defaults if using default data directories; otherwise check your backend and paths before initialization.

Initialize storage on first startup or after adding graph configuration under conf/graphs/:

1# Enter the extracted or built Server directory
2cd apache-hugegraph-*/apache-hugegraph-server-*
3bin/init-store.sh

Start Server and preload the built-in sample graph:

1bin/start-hugegraph.sh -p true

The startup script polls /graphs at configured restserver.url and exits nonzero on timeout or process failure. Check service version, then read sample vertices:

1curl -fsS http://127.0.0.1:8080/versions
2curl --compressed -fsS \
3  http://127.0.0.1:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices

The first response should contain versions; the second should contain vertices with sample names such as marko and lop. A process check or HTTP status alone does not prove backend and business request health.

ToplingDB (Beta): A high-performance RocksDB alternative; see the ToplingDB Quick Start.

5.1.3 HBase

Note

users need to install HBase by themselves, requiring version 2.0 or above,download link

HBase configuration and startup methods

Update hugegraph.properties

 1backend=hbase
 2serializer=hbase
 3
 4# hbase backend config
 5hbase.hosts=localhost
 6hbase.port=2181
 7# Note: recommend to modify the HBase partition number by the actual/env data amount & RS amount before init store
 8# it may influence the loading speed a lot
 9#hbase.enable_partition=true
10#hbase.vertex_partitions=10
11#hbase.edge_partitions=30

Initialize the database (required on the first startup, or a new configuration was manually added under ‘conf/graphs/’)

1cd *hugegraph-${version}
2bin/init-store.sh

Start server

1bin/start-hugegraph.sh
2Starting HugeGraphServer in daemon mode...
3Connecting to HugeGraphServer (http://127.0.0.1:8080/graphs)....OK
4Started [pid 21614]

5.1.4 Create an example graph when startup

Pass the -p true argument when starting the script to enable preload, which creates a sample graph.

1bin/start-hugegraph.sh -p true
2Starting HugeGraphServer in daemon mode...
3Connecting to HugeGraphServer (http://127.0.0.1:8080/graphs)......OK

And use the RESTful API to request HugeGraphServer and get the following result:

1> curl "http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices" | gunzip
2
3{"vertices":[{"id":"2:lop","label":"software","type":"vertex","properties":{"name":"lop","lang":"java","price":328}},{"id":"1:josh","label":"person","type":"vertex","properties":{"name":"josh","age":32,"city":"Beijing"}},{"id":"1:marko","label":"person","type":"vertex","properties":{"name":"marko","age":29,"city":"Beijing"}},{"id":"1:peter","label":"person","type":"vertex","properties":{"name":"peter","age":35,"city":"Shanghai"}},{"id":"1:vadas","label":"person","type":"vertex","properties":{"name":"vadas","age":27,"city":"Hongkong"}},{"id":"2:ripple","label":"software","type":"vertex","properties":{"name":"ripple","lang":"java","price":199}}]}

This indicates the successful creation of the sample graph.

5.1.5 Startup script options

bin/start-hugegraph.sh accepts the following options. Every one of them takes a value, so write -d false, not a bare -d.

OptionValuesDefaultPurpose
-dtrue, falsetrueDaemon mode. With -d false the script stays in the foreground and forwards SIGTERM/SIGINT to the server.
-gg1, G1, zgc, ZGCJVM defaultGarbage collector to use (g1/G1 sets -XX:+UseG1GC; zgc/ZGC sets -XX:+UseZGC). Omitting -g uses the JVM default collector.
-mtrue, falsefalseInstall the cron-based monitor task (bin/start-monitor.sh). For VM and bare-metal deployments only.
-ptrue, falsefalsePreload the sample graph, as in 5.1.4.
-strue, falsetrueEnable HugeSecurityManager; requires Java 17 to 23 and readable conf/java-security.properties. On Java 24+, start with -s false.
-jJVM optionsemptyExtra JVM options appended to the server command line.
-tseconds30How long to wait for the service to answer before reporting a failed startup.
-ytrue, falsefalseEnable the OpenTelemetry agent for traces.

bin/stop-hugegraph.sh accepts -m true|false (default true), which controls whether the cron monitor task is removed along with the service.

bin/hugegraph-server.sh puts -XX:+HeapDumpOnOutOfMemoryError, -XX:HeapDumpPath and -XX:ErrorFile first in JAVA_TOOL_OPTIONS, so, whether or not JAVA_OPTIONS is set and with the exceptions below, an out-of-memory heap dump (heapdump_<host>_<launch time>/java_pid<pid>.hprof) and a JVM crash log (hs_err_pid<pid>_<host>_<launch time>.log) land in logs/, where <launch time> is the local time as YYYYMMDD-HHMMSS. Each start gets its own heapdump_* directory, so the server and the JVMs it starts, such as computer jobs, write separate dumps (HotSpot names each dump and crash log after the JVM’s PID, so a JVM that reuses an earlier PID from the same start cannot write its dump, and its crash log replaces the earlier one’s). The host name keeps servers that share one log directory from picking the same name, and a counter (<launch time>-1, -2, …) is added when the same host already used that second. If the directory cannot be created, for example on a full disk, the server still starts and dumps go to logs/ itself, as a best effort: a full disk may have no room for the dump either. A heap dump can be as large as the heap. The launcher never deletes dumps or heapdump_* directories: each start that reaches Java leaves one, empty unless something ran out of memory, and the launcher keeps it because a computer-job JVM can go on using it after the server exits. Move or delete old ones once no HugeGraph JVM from that launch is running, but never the newest one of a running server; without it, the next dump is written as a file with that name. The JVM reads your own JAVA_TOOL_OPTIONS, JDK_JAVA_OPTIONS (including @argfiles), the command line (JAVA_OPTIONS, or -j when JAVA_OPTIONS is unset or empty) and _JAVA_OPTIONS after these defaults, so a value for one of these flags in any of them overrides the default. Only the environment variables reach the JVMs the server starts: to turn dumps off for all of them, set JAVA_TOOL_OPTIONS=-XX:-HeapDumpOnOutOfMemoryError, while -j or JAVA_OPTIONS turns them off for the server JVM only. Either way each start that reaches Java still creates its empty heapdump_* directory, unless creating it failed and dumps fell back to logs/. If the logs path contains a double quote or %, the launcher warns and heap dumps go to logs/ itself, with no per-launch directory and no crash log default; the JAVA_TOOL_OPTIONS opt-out still applies. A path with both quote characters gets no heap dump default at all. Because of the defaults, the JVM prints Picked up JAVA_TOOL_OPTIONS: ... on stderr at startup.

Version scope: this applies to current development/master builds. In 1.7.0 the heap dump flags are added only when JAVA_OPTIONS is unset, heap dumps go directly to logs/java_pid<pid>.hprof, and JVM crash logs go to the install directory.

5.2 Use Docker to startup

In 3.1 Use Docker container, we introduced how to deploy hugegraph-server with Docker. You can also switch storage backends or preload a sample graph by setting the corresponding parameters.

5.2.1 Create an example graph when starting a server

Set the environment variable PRELOAD=true when starting Docker so that sample data is loaded during startup.

  1. Use docker run

    Use docker run -itd --name=server -p 8080:8080 -e PRELOAD=true hugegraph/hugegraph:1.7.0

  2. Use docker-compose

    Create a docker-compose.yml file like the following and set PRELOAD=true in the environment. example.groovy is a predefined script used to preload sample data. If needed, you can mount a new example.groovy script to change the preload data.

     1version: '3'
     2services:
     3  server:
     4    image: hugegraph/hugegraph:1.7.0
     5    container_name: server
     6    environment:
     7      - PRELOAD=true
     8      - PASSWORD=xxx
     9    volumes:
    10      - /path/to/yourscript:/hugegraph-server/scripts/example.groovy
    11    ports:
    12      - 8080:8080

    Server images built from current master run as the non-root UID 10001, so a mounted script must be readable by that user.

    Use docker compose up -d to start the container.

And use the RESTful API to request HugeGraphServer and get the following result:

1> curl "http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices" | gunzip
2
3{"vertices":[{"id":"2:lop","label":"software","type":"vertex","properties":{"name":"lop","lang":"java","price":328}},{"id":"1:josh","label":"person","type":"vertex","properties":{"name":"josh","age":32,"city":"Beijing"}},{"id":"1:marko","label":"person","type":"vertex","properties":{"name":"marko","age":29,"city":"Beijing"}},{"id":"1:peter","label":"person","type":"vertex","properties":{"name":"peter","age":35,"city":"Shanghai"}},{"id":"1:vadas","label":"person","type":"vertex","properties":{"name":"vadas","age":27,"city":"Hongkong"}},{"id":"2:ripple","label":"software","type":"vertex","properties":{"name":"ripple","lang":"java","price":199}}]}

This indicates that the sample graph was created successfully.

6. Access server

6.1 Service startup status check

Use jps to see a service process

1jps
26475 HugeGraphServer

curl request RESTfulAPI

1curl -fsS http://127.0.0.1:8080/versions

HTTP 2xx with a JSON versions field confirms REST responsiveness. HugeGraphServer in jps confirms only process existence; verify backend health by preloading the sample graph and requesting vertices as above.

6.2 Request Server

The RESTful API of HugeGraphServer includes various types of resources, typically including graph, schema, gremlin, traverser and task.

  • graph contains vertices、edges
  • schema contains vertexlabels、 propertykeys、 edgelabels、indexlabels
  • gremlin contains various Gremlin statements, such as g.v(), which can be executed synchronously or asynchronously
  • traverser contains various advanced queries including shortest paths, intersections, N-step reachable neighbors, etc.
  • task contains query and delete with asynchronous tasks
1curl http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices

explanation

  1. Server can compress vertex, edge, and other list responses. Use curl --compressed for automatic decompression:

    1curl --compressed -fsS "http://localhost:8080/graphspaces/DEFAULT/graphs/hugegraph/graph/vertices"
  2. The default listener is 127.0.0.1, inaccessible directly from other machines.

    1vim conf/rest-server.properties
    2
    3restserver.url=http://0.0.0.0:8080
Warning

Changing the Server listener

Setting 0.0.0.0 listens on every interface. In production, enable authentication and authorization, an IP allowlist, and minimum permissions; retain and protect audit logs. Do not expose Gremlin or Cypher directly to the public Internet.

response body:

 1{
 2    "vertices": [
 3        {
 4            "id": "2lop",
 5            "label": "software",
 6            "type": "vertex",
 7            "properties": {
 8                "price": [
 9                    {
10                        "id": "price",
11                        "value": 328
12                    }
13                ],
14                "name": [
15                    {
16                        "id": "name",
17                        "value": "lop"
18                    }
19                ],
20                "lang": [
21                    {
22                        "id": "lang",
23                        "value": "java"
24                    }
25                ]
26            }
27        },
28        {
29            "id": "1josh",
30            "label": "person",
31            "type": "vertex",
32            "properties": {
33                "name": [
34                    {
35                        "id": "name",
36                        "value": "josh"
37                    }
38                ],
39                "age": [
40                    {
41                        "id": "age",
42                        "value": 32
43                    }
44                ]
45            }
46        },
47        ...
48    ]
49}

For the detailed API, please refer to RESTful-API

You can also visit localhost:8080/swagger-ui/index.html to check the API.

HugeGraph RESTful API endpoints in Swagger UI

When using Swagger UI to debug the API provided by HugeGraph, if HugeGraph Server turns on authentication mode, you can enter authentication information on the Swagger page.

Authorize button in the HugeGraph Swagger UI

Currently, HugeGraph supports setting authentication information in two forms: Basic and Bearer.

Basic and Bearer credential fields in the Swagger UI authorization dialog

7 Stop Server

1# From within the Server directory
2bin/stop-hugegraph.sh

8 Debug Server with IntelliJ IDEA

Please refer to Setup Server in IDEA

2 - HugeGraph-PD Quick Start

1 HugeGraph-PD Overview

HugeGraph-PD (Placement Driver) is the metadata management component of HugeGraph’s distributed version, responsible for managing the distribution of graph data and coordinating storage nodes. It plays a central role in distributed HugeGraph, maintaining cluster status and coordinating HugeGraph-Store storage nodes.

PD keeps cluster metadata in an embedded RocksDB store under pd.data-path and replicates it across PD nodes with Raft, so a 3-node or 5-node PD cluster keeps serving while a minority of nodes is down. On top of that it registers and activates Store nodes, allocates and rebalances partitions, tracks Store heartbeats, and answers service discovery queries from Store and Server.

PD listens on three ports:

PortDefaultConfigured byUsed by
gRPC8686grpc.portStore and Server clients
REST8620server.portManagement, health checks, metrics
Raft8610raft.addressThe other PD nodes only

2 Prerequisites

2.1 Requirements

  • Operating System: Linux or macOS (Windows has not been fully tested)
  • Java version: Java 17 for HugeGraph 1.8.0+ (the Maven build accepts only JDK 17; the start script rejects older runtimes; 1.7.0 is the last release supporting Java 11)
  • Maven version: ≥ 3.6.3 (for building from source)

3 Deployment

Choose a deployment method for the HugeGraph-PD component:

3.1 Download the tar package

Apache downloads currently provide the complete 1.7.0 binary bundle containing PD, Store, and Server, without a separate PD binary. Verify version, signatures, and SHA512 on the official download page. This historical incubating release retains incubating in archive and extracted directory names:

1# Historical release 1.7.0 retains incubating in filenames and directories
2curl -fLO --connect-timeout 10 --max-time 1800 https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-incubating-1.7.0.tar.gz
3tar zxf apache-hugegraph-incubating-1.7.0.tar.gz
4cd apache-hugegraph-incubating-1.7.0/apache-hugegraph-pd-incubating-1.7.0

3.2 Compile from source

  1. Clone the source code:

    1git clone https://github.com/apache/hugegraph.git
    2cd hugegraph
  2. Build the PD module:

    1# Build only the PD distribution and its dependencies
    2mvn clean package -pl hugegraph-pd/hg-pd-dist -am -DskipTests
  3. Locate the distribution output:

    1cd hugegraph-pd/apache-hugegraph-pd-*/
    2ls -la bin conf lib

The unpacked distribution contains just three directories: bin (start and stop scripts), conf (application.yml, application.yml.template, log4j2.xml, verify-license.json) and lib (the hg-pd-service jar).

3.3 Docker Deployment

HG_PD_* mappings and /v1/ready are features of current master; the Server 1.7.0 source tag lacks these Docker mappings and readiness API. The following examples require images built from current master and tagged local. For release 1.7.0 assets, use bundled configuration and version-specific instructions:

1# Run from the HugeGraph repository root
2docker build -f hugegraph-pd/Dockerfile -t hugegraph/pd:local .

To run master-built PD alone, first set a deployment-specific secret and replace example addresses with addresses reachable by the container:

The mkdir -p and nonrecursive chown below are for a new empty directory. Before reusing data written by a root image, stop PD and run sudo chown -R 10001:10001 /path/to/data once, then start the UID 10001 image.

 1export HG_PD_AUTH_SECRET_KEY="$(openssl rand -hex 24)"
 2# Master-built images run as UID 10001; the host data directory must be writable by it
 3mkdir -p /path/to/data && sudo chown 10001:10001 /path/to/data
 4docker run -d \
 5  -p 8620:8620 -p 8686:8686 -p 8610:8610 \
 6  -e HG_PD_GRPC_HOST=192.168.1.10 \
 7  -e HG_PD_RAFT_ADDRESS=192.168.1.10:8610 \
 8  -e HG_PD_RAFT_PEERS_LIST=192.168.1.10:8610 \
 9  -e HG_PD_INITIAL_STORE_LIST=192.168.1.20:8500 \
10  -e HG_PD_AUTH_SECRET_KEY="$HG_PD_AUTH_SECRET_KEY" \
11  -v /path/to/data:/hugegraph-pd/pd_data \
12  --name hugegraph-pd \
13  hugegraph/pd:local
VariableRequiredDefaultConfiguration keyDescription
HG_PD_GRPC_HOSTYesNonegrpc.hostAdvertised gRPC hostname/IP; use container hostnames within a container network.
HG_PD_RAFT_ADDRESSYesNoneraft.addressThis PD node’s Raft address.
HG_PD_RAFT_PEERS_LISTYesNoneraft.peers-listRaft addresses of every PD node, including this node.
HG_PD_INITIAL_STORE_LISTYesNonepd.initial-store-listExpected Store gRPC addresses.
HG_PD_AUTH_SECRET_KEYYesNoneauth.secret-keyREST Basic password shared by all PD REST clients.
HG_PD_GRPC_PORTNo8686grpc.portgRPC service port.
HG_PD_REST_PORTNo8620server.portREST API port.
HG_PD_DATA_PATHNo/hugegraph-pd/pd_datapd.data-pathMetadata path.
HG_PD_INITIAL_STORE_COUNTNo1pd.initial-store-countMinimum Store count needed for cluster availability.
HG_PD_ACTUATOR_EXPOSURENohealth,metrics,prometheusmanagement.endpoints.web.exposure.includePublic Actuator endpoint allowlist; * is forbidden.

The master entrypoint requires all five mandatory variables, builds SPRING_APPLICATION_JSON overrides, then starts PD. Other settings come from image conf/application.yml; JAVA_OPTS is passed to the JVM. Deprecated GRPC_HOST, RAFT_ADDRESS, RAFT_PEERS, and PD_INITIAL_STORE_LIST remain supported with warnings.

Docker HEALTHCHECK polls /v1/health every 15 seconds, confirming only REST listener liveness, not a Raft quorum. Compose uses the same liveness check; verify /v1/ready separately before starting Store. Containers run Java in the foreground and exit when Java exits; automatic restart requires a Docker restart policy. Inspect logs with docker logs <container-name>.

See the Store Docker section and docker/README.md for master Compose and the minimal topology. When starting the full topology with Hubble, first generate the untracked Hubble configuration described in that README.

4 Configuration

PD startup reads installation conf/application.yml. Match this file to the installed version: 1.7.0 configuration or master configuration. Master leaves auth.secret-key empty, causing protected REST calls to be rejected until configured. Startup does not read application.yml.template.

4.1 Configuration Reference

These tables list master configuration values and code defaults. See the PDConfig implementation for Raft timeouts. Use the original tagged configuration with 1.7.0 binaries and master configuration with master builds. Differences from 1.7.0 are noted below.

gRPC and REST

KeyMaster distribution valueBuilt-in defaultDescription
grpc.host127.0.0.1none, requiredAddress this PD advertises for gRPC. Store and Server connect here, so set it to a reachable IPv4 address or hostname, never 127.0.0.1 or 0.0.0.0, in a distributed deployment.
grpc.port8686none, requiredgRPC port.
server.port8620none, requiredREST API port. Also the port reported in Raft member information.

application.yml.template also carries grpc.netty-server.max-inbound-message-size: 100MB, but PD sets the gRPC server’s inbound message limit to 1 GB in code, so that key has no effect.

Raft

KeyMaster distribution valueBuilt-in defaultDescription
raft.address127.0.0.1:8610none, requiredRaft address of this node as host:port. Must be unique per node and must appear in raft.peers-list.
raft.peers-list127.0.0.1:8610none, requiredComma separated Raft addresses of every PD node, including this one. Must be identical on all nodes.
raft.enablenot settrueWhen true, metadata writes go through the Raft state machine. When false, PD writes straight to its local store with no replication.
raft.ip-whitelist.enablednot settrueWhen true, the Raft RPC port accepts connections only from the addresses resolved from raft.peers-list; other clients are dropped and logged as Blocked connection from <ip>. The allowlist is re-resolved when the peer list changes, but a peer that keeps its hostname and changes IP (a restarted container, for example) needs a PD restart.
raft.snapshotIntervalnot set300Seconds between Raft snapshots.
raft.rpc-timeoutnot set10000Timeout of a Raft RPC between PD nodes, in milliseconds. Also the deadline of the ReadIndex wait that PD runs before it reads an id counter; id allocation fails when the wait takes longer.
raft.rpc-connect-timeoutnot set1000Timeout of the Ping that opens a Raft connection to a peer, in milliseconds. A candidate connects to its peers one at a time, so an election waits this long for each peer that accepts the TCP connection but does not answer. Requests on an open connection use raft.rpc-timeout.
raft.rpc-install-snapshot-timeoutnot set0Timeout for sending a snapshot to a follower that fell behind the log, in milliseconds. 0 uses raft.rpc-timeout. Raise it if large snapshots time out.

raft.rpc-connect-timeout and raft.rpc-install-snapshot-timeout exist only in versions after 1.7.0. In 1.7.0, raft.rpc-timeout is also the connect and install-snapshot timeout, and id allocation runs no ReadIndex wait.

PD core

KeyMaster distribution valueBuilt-in defaultDescription
pd.data-path./pd_datanone, requiredMetadata directory. Holds the RocksDB store in rocksdb/ and the Raft log, metadata and snapshots in pd_raft/.
pd.patrol-interval1800300Seconds between patrol runs, which check partition health across stores and rebalance partition counts.
pd.initial-store-count13Minimum number of active Store nodes. Below this the cluster state becomes Cluster_Not_Ready and the cluster is treated as unavailable. Set it to the number of stores you deploy.
pd.min-store-countnot set0Minimum active Store count required during Store drain/retirement checks. If remaining active stores fall below this value, the transition to Exiting is rejected.
pd.initial-store-list127.0.0.1:8500emptyComma separated Store gRPC addresses (ip:port) that are activated automatically when they register. An entry may also carry a group id as store_address/group_id.
pd.cluster_idnot set1Cluster id, used to keep separate PD clusters apart.

Store management

KeyMaster distribution valueBuilt-in defaultDescription
store.keepAlive-timeoutnot set300Seconds without a heartbeat after which a Store is treated as temporarily unavailable and its partition leaders move to other replicas.
store.max-down-time1728001800Seconds after which a Store is treated as permanently unavailable and its replicas are reallocated to other machines.
store.monitor_data_enabledtruefalseWhether to persist Store monitoring samples.
store.monitor_data_interval1 minute1 minuteSampling interval, written as <number> <unit> with unit one of second, minute, hour, day, month, year. The number defaults to 1 when omitted.
store.monitor_data_retention1 day1 dayHow long monitoring samples are kept, same format as above.

Partitions

KeyMaster distribution valueBuilt-in defaultDescription
partition.default-shard-count13Number of replicas per partition. Use 3 for a production cluster.
partition.store-max-shard-count1224Maximum number of partition replicas one Store holds.

The initial partition count is derived from these two values and the size of pd.initial-store-list:

1initial partitions = store count * partition.store-max-shard-count / partition.default-shard-count

Discovery, license and metrics

KeyMaster distribution valueBuilt-in defaultDescription
discovery.heartbeat-try-countnot set3Number of missed heartbeats after which a registered client’s discovery entry is deleted.
license.verify-path./conf/verify-license.jsonNone; required configuration keyThe PD distribution includes this JSON file; current master has no runtime read of this configuration option.
license.license-path./conf/hugegraph.licenseNone; required configuration keyNo license file is bundled at this path. Internal gRPC putLicense writes uploads here. Master REST GET /v1/license returns an empty object; a missing file does not block startup.
auth.secret-keyEmptyEmptyMaster PD REST Basic password for usernames hg, store, hubble, or vermeer. Docker requires it; bare-metal PD can start with an empty secret, but rejects protected REST calls.
management.metrics.export.prometheus.enabledtrueSpring Boot defaultExposes /actuator/prometheus.
management.endpoints.web.exposure.includehealth,metrics,prometheusSpring Boot exposes only health by defaultActuator allowlist; these endpoints bypass the PD REST Basic interceptor.
logging.configfile:./conf/log4j2.xmlnoneLog4j2 configuration. Writes logs/hugegraph-pd.log, logs/hugegraph-pd_raft.log and logs/audit-hugegraph-pd.log.

Thread pools

KeyBuilt-in defaultDescription
thread.pool.grpc.core600Core size of the pool that serves gRPC calls.
thread.pool.grpc.max1000Maximum size of that pool.
thread.pool.grpc.queueunboundedQueue capacity of that pool.
job.uninterruptibleThreadPool.core0Core size of the background metadata job pool. A value of 0 or less means half the available processors.
job.uninterruptibleThreadPool.max256Maximum size of that pool.
job.uninterruptibleThreadPool.queueunboundedQueue capacity of that pool.

4.2 Single-node configuration

For master-built distributions, start with conf/application.yml, adjust per-node gRPC/Raft addresses and data paths, and set auth.secret-key. The following values are for development and testing. One PD node provides no majority fault tolerance; partition.default-shard-count: 1 means one replica per partition.

 1grpc:
 2  host: 127.0.0.1
 3  port: 8686
 4server:
 5  port: 8620
 6raft:
 7  address: 127.0.0.1:8610
 8  peers-list: 127.0.0.1:8610
 9pd:
10  data-path: ./pd_data
11  initial-store-count: 1
12  initial-store-list: 127.0.0.1:8500
13partition:
14  default-shard-count: 1
15auth:
16  secret-key: replace-with-deployment-secret

Generate a deployment secret with openssl rand -hex 24; Docker supplies it through HG_PD_AUTH_SECRET_KEY. See REST API authentication for the different 1.7.0 behavior.

4.3 Three-node cluster configuration

For a production cluster run 3 or 5 PD nodes, an odd number so Raft always has a quorum. A 3-node cluster tolerates one node failure. raft.peers-list must list every node and must be byte-for-byte identical on all of them, while grpc.host and raft.address differ per node.

Node 1 (192.168.1.10):

 1grpc:
 2  host: 192.168.1.10
 3  port: 8686
 4server:
 5  port: 8620
 6raft:
 7  address: 192.168.1.10:8610
 8  peers-list: 192.168.1.10:8610,192.168.1.11:8610,192.168.1.12:8610
 9pd:
10  data-path: /data/pd
11  initial-store-count: 3
12  initial-store-list: 192.168.1.20:8500,192.168.1.21:8500,192.168.1.22:8500
13partition:
14  default-shard-count: 3

Node 2 (192.168.1.11) and node 3 (192.168.1.12) use the same file with grpc.host and raft.address changed to their own address:

 1# Node 2
 2grpc:
 3  host: 192.168.1.11
 4raft:
 5  address: 192.168.1.11:8610
 6  peers-list: 192.168.1.10:8610,192.168.1.11:8610,192.168.1.12:8610
 7
 8# Node 3
 9grpc:
10  host: 192.168.1.12
11raft:
12  address: 192.168.1.12:8610
13  peers-list: 192.168.1.10:8610,192.168.1.11:8610,192.168.1.12:8610

To put all three PD nodes on one machine for testing, give each node its own pd.data-path and its own ports, for example raft 8610/8611/8612, gRPC 8686/8687/8688 and REST 8620/8621/8622.

In Docker bridge networking the same configuration comes from environment variables and uses container hostnames instead of IP addresses:

 1# Share the same secret across PD nodes; inject it from private environment variables
 2HG_PD_AUTH_SECRET_KEY: ${HG_PD_AUTH_SECRET_KEY:?set HG_PD_AUTH_SECRET_KEY}
 3
 4# pd0
 5HG_PD_GRPC_HOST: pd0
 6HG_PD_RAFT_ADDRESS: pd0:8610
 7HG_PD_RAFT_PEERS_LIST: pd0:8610,pd1:8610,pd2:8610
 8HG_PD_INITIAL_STORE_LIST: store0:8500,store1:8500,store2:8500
 9HG_PD_INITIAL_STORE_COUNT: 3
10
11# pd1
12HG_PD_GRPC_HOST: pd1
13HG_PD_RAFT_ADDRESS: pd1:8610
14HG_PD_RAFT_PEERS_LIST: pd0:8610,pd1:8610,pd2:8610
15
16# pd2
17HG_PD_GRPC_HOST: pd2
18HG_PD_RAFT_ADDRESS: pd2:8610
19HG_PD_RAFT_PEERS_LIST: pd0:8610,pd1:8610,pd2:8610

5 Start and Stop

5.1 Start PD

In the PD installation directory, execute:

1./bin/start-hugegraph-pd.sh

The script requires Java 17 or later on PATH or in JAVA_HOME (Java ≥ 11 on 1.7.0). It exits without doing anything if it finds a Java process already using this installation’s conf directory.

The lifecycle details below describe current master builds. The downloaded 1.7.0 launcher does not include those repairs. Supported flags, with GC version limits noted below:

FlagValuesDefaultDescription
-dtrue, falsetrueDaemon mode. See the note below.
-gSee version limits belownot setSelect the garbage collector. Unsupported values abort startup.
-jJVM optionsemptyExtra JVM options, for example -j "-Xmx8g -Xms8g".
-ytrue, falsefalseAttach the OpenTelemetry Java agent. The agent is downloaded into plugins/ on first use, its MD5 is verified, and traces are exported over gRPC to http://127.0.0.1:4317.

Master builds accept g1, G1, zgc and ZGC. The downloaded 1.7.0 launcher accepts only zgc or ZGC as explicit choices; -g g1, -g G1 and other values abort startup. Omit -g for the default path. For rejected values, inspect logs/hugegraph-pd-stdout.log.

The -d flag controls daemon mode:

  • -d true (default): run as a background daemon; the script returns immediately.
  • -d false: run in foreground. The script execs Java, so the container or supervisor process IS Java. Use this when running under Docker or a process supervisor (systemd, supervisord) so crashes are detected and the service is restarted automatically.

Each flag also has an environment variable equivalent: DAEMON, GC_OPTION, USER_OPTION and OPEN_TELEMETRY. Setting JAVA_OPTIONS replaces the computed heap settings entirely; otherwise the script sizes the heap between 512 MB and 32 GB from available memory. Setting STDOUT_MODE=true leaves the JVM output on stdout instead of redirecting it to logs/hugegraph-pd-stdout.log, which is what the Docker image does.

After successful startup, you can see logs similar to the following in logs/hugegraph-pd-stdout.log:

1YYYY-mm-dd xx:xx:xx [main] [INFO] o.a.h.p.b.HugePDServer - Started HugePDServer in x.xxx seconds (JVM running for x.xxx)

The process id is written to bin/pid.

5.2 Stop PD

In the PD installation directory, execute:

1./bin/stop-hugegraph-pd.sh

The script reads bin/pid, sends the process a termination signal, waits up to 30 seconds for it to exit, and removes the pid file. If bin/pid is missing it reports that and exits successfully.

6 Startup Order in a Distributed Cluster

Start the components in this order:

  1. All PD nodes. Form the Raft group and elect a leader. Check GET /v1/ready on each node; start Store only after HTTP 200 with ready:true. /v1/health checks REST listener liveness only.
  2. All Store nodes. Register with PD; wait for /v1/stores to show every target Store as Up.
  3. All Server nodes. Start after PD and Store are ready.
sequenceDiagram
    participant Operator
    participant PD
    participant Store
    participant Server
    Operator->>PD: GET /v1/ready (check each PD)
    PD-->>Operator: HTTP 200 and ready=true
    Operator->>Store: Start Store
    Store->>PD: gRPC registration and heartbeat
    Operator->>PD: GET /v1/stores (Basic authentication)
    PD-->>Operator: Every target Store is Up
    Operator->>Server: Start Server
    Server->>PD: gRPC partitions and discovery
    Server->>Store: gRPC graph data access

Master Compose waits on PD /v1/health through Store depends_on: condition: service_healthy, and on Store REST liveness before Server. Server also polls PD /v1/stores for an Up Store before starting. Therefore, docker compose up --wait does not replace PD Raft readiness and Store registration checks.

PD is also the last component to stop: shut down Server, then Store, then PD.

7 Verification

7.1 REST API Authentication

Current master requires HTTP Basic Authorization for all PD REST paths except /actuator/*, /v1/health, /v1/ready, and /v1/prom/targets/*. Username must be hg, store, hubble, or vermeer, and password must equal auth.secret-key. A missing secret or wrong password returns HTTP 401. Query Stores using the same secret configured at PD startup:

1{"status": -1, "error": "Unauthorized"}
1curl -u "store:${HG_PD_AUTH_SECRET_KEY:?Set the PD deployment secret first}" \
2  http://localhost:8620/v1/stores

bin/wait-storage.sh uses the same credentials through PD_AUTH_USER and PD_AUTH_PASSWORD. Release 1.7.0 checks only internal service usernames and does not compare passwords; do not apply this older behavior to master builds.

Warning

Protect Server and PD ports separately in production

Enable Server authentication and authorization, an IP allowlist, and minimum graph API permissions; retain and protect Server audit-*.log. These controls do not protect PD. Master PD REST uses auth.secret-key, whereas 1.7.0 checks usernames only. Keep raft.ip-whitelist.enabled enabled for configured peers and restrict PD REST/gRPC to trusted networks. Unauthenticated /v1/health, /v1/ready, and Actuator probes require network restrictions too. Protect master PD audit logs at logs/audit-hugegraph-pd.log.

7.2 Health Checks

Unauthenticated GET /v1/health returns 200 with an empty body, confirming only PD REST listener startup:

1curl -i http://localhost:8620/v1/health

Spring Boot Actuator also provides a readable health response:

1curl http://localhost:8620/actuator/health

Actuator {"status":"UP"} does not confirm an available PD Raft leader. Master GET /v1/ready returns HTTP 200 with ready:true when the PD Raft node is active and sees a leader; otherwise it returns HTTP 503 with ready:false:

1curl -i http://localhost:8620/v1/ready

7.3 Cluster and member status

Check the PD members and which node is the Raft leader:

1curl -u "store:${HG_PD_AUTH_SECRET_KEY:?Set the PD deployment secret first}" \
2  http://localhost:8620/v1/members

The response carries pdList, the elected pdLeader, numOfService, numOfNormalService and a stateCountMap. In a healthy 3-node PD cluster numOfService and numOfNormalService are both 3 and exactly one member has role: "Leader".

GET /v1/cluster returns the same member list together with the Store list, graph list and overall cluster state, and GET / returns a short summary (leader address, cluster state, member count, store count, graph count, partition count).

7.4 Store status

You can also verify Store node status through the PD API:

1curl -u "store:${HG_PD_AUTH_SECRET_KEY:?Set the PD deployment secret first}" \
2  http://localhost:8620/v1/stores

If the response shows state as Up, the corresponding Store node is running normally. The example below shows a single Store node. In a healthy 3-node deployment, the storeId list should contain three IDs, and stateCountMap.Up, numOfService, and numOfNormalService should all be 3.

 1{
 2  "message": "OK",
 3  "data": {
 4    "stores": [
 5      {
 6        "storeId": 8319292642220586694,
 7        "address": "127.0.0.1:8500",
 8        "raftAddress": "127.0.0.1:8510",
 9        "version": "",
10        "state": "Up",
11        "deployPath": "/Users/{your_user_name}/hugegraph/apache-hugegraph-incubating-1.7.0/apache-hugegraph-store-incubating-1.7.0/lib/hg-store-node-1.7.0.jar",
12        "dataPath": "./storage",
13        "startTimeStamp": 1754027127969,
14        "registedTimeStamp": 1754027127969,
15        "lastHeartBeat": 1754027909444,
16        "capacity": 494384795648,
17        "available": 346535829504,
18        "partitionCount": 0,
19        "graphSize": 0,
20        "keyCount": 0,
21        "leaderCount": 0,
22        "serviceName": "127.0.0.1:8500-store",
23        "serviceVersion": "",
24        "serviceCreatedTimeStamp": 1754027127000,
25        "partitions": []
26      }
27    ],
28    "stateCountMap": {
29      "Up": 1
30    },
31    "numOfService": 1,
32    "numOfNormalService": 1
33  },
34  "status": 0
35}

7.5 Other REST endpoints

All paths below are relative to http://<pd-host>:8620 and need the Basic header from section 7.1 unless noted.

Method and pathDescription
GET /Brief cluster statistics: leader, state, member count, store count, graph count, partition count
GET /v1/healthLiveness only; HTTP 200 does not imply Raft readiness; no authentication
GET /v1/readyMaster readiness: HTTP 200 with ready:true means an active node that sees a leader; no authentication
GET /v1/clusterFull cluster statistics: PD members, stores, graphs, partitions
GET /v1/membersPD member list with roles and the elected leader
POST /v1/members/changeChange the Raft peer list, body {"peerList": "..."}
GET /v1/storesRegistered Store nodes with state and per-store statistics
GET /v1/store/{storeId}One Store node
POST /v1/store/{storeId}Update a Store’s state, body {"storeState": "..."}
DELETE /v1/store/{storeId}Remove a Store from the cluster
POST /v1/store/logStore state change log, body {"startTime": "...", "endTime": "..."}
GET /v1/storesAndStatsRaw Store metadata, for debugging
GET /v1/store_monitor/{storeId}Store monitoring samples as text
GET /v1/store_monitor/json/{storeId}Store monitoring samples as JSON
GET /v1/shardsEvery shard of every partition, with store id, role, state and progress
GET /v1/shardGroupsShard groups
GET /v1/shardGroupsCacheShard groups from PD’s in-memory cache
GET /v1/shardLeadersPartition leaders grouped by Store raft address
GET /v1/balanceLeadersRebalance partition leaders across Stores
GET /v1/partitionsPartition list with state and statistics
GET /v1/highLevelPartitionsPartitions with per-graph key counts and data sizes
GET /v1/partitionsAndStatsRaw partition metadata, for debugging
POST /v1/partitions/logPartition change log, body {"startTime": "...", "endTime": "..."}
GET /v1/resetPartitionStateReset the state of every partition
GET /v1/graphsGraph list
GET /v1/graph/**One graph by name
POST /v1/graph/**Update a graph’s partition count, body {"partitionCount": N}
GET /v1/graph/partitionSizeRangeMinimum and maximum partition count the cluster accepts
GET /v1/graph-spacesGraph space list
GET /v1/graph-spaces/**One graph space
POST /v1/graph-spaces/**Update a graph space
POST /v1/registryRegister a service instance for discovery
POST /v1/registryInfoQuery registered instances
GET /v1/allInfoAll registered instances
GET /v1/licenseLegacy endpoint; current master returns an empty object
GET /v1/license/machineInfoIP and MAC addresses seen by the license check
GET /v1/task/patrolStoresRun the store patrol task now
GET /v1/task/patrolPartitionsRun the partition patrol task now
GET /v1/task/balancePartitionsRebalance partitions across Stores
GET /v1/task/splitPartitionsRun automatic partition splitting now
GET /v1/task/balanceLeadersRebalance partition leaders
GET /v1/task/compactInstruct Store nodes to compact the RocksDB files of their partitions
GET /v1/prom/targets/{appName}Prometheus service discovery targets, no authentication required
GET /v1/prom/targets-allPrometheus targets for all app types
GET /v1/prom/sd_configPrometheus HTTP service discovery config
GET /actuator/healthSpring Boot health, no authentication required
GET /actuator/metricsSpring Boot metrics, no authentication required
GET /actuator/prometheusPrometheus scrape endpoint, no authentication required

The two log endpoints take a time range as {"startTime": "...", "endTime": "..."}; yyyy-MM-dd HH:mm:ss and yyyy-MM-dd are among the accepted formats.

PD registers its own meters under the hg prefix, so /actuator/prometheus exposes hg_up, hg_graphs, hg_stores and hg_terms alongside the standard JVM metrics, plus per-graph partition and size meters once graphs exist.

It also exposes Raft membership gauges for monitoring and alerting on quorum loss:

  • hg_raft_leader: 1 if this PD node is the elected Raft leader, 0 otherwise.
  • hg_raft_has_leader: 1 if this PD node observes an active Raft leader (i.e. is part of a quorum), 0 when quorum is lost.
  • hg_raft_alive_peers: Number of active Raft peers (including itself) that the leader has heard from within the leader lease timeout; reported as NaN on non-leader follower nodes.
Note

Quorum Loss Alerting: Cluster quorum is lost when sum(hg_raft_leader) == 0 or hg_raft_has_leader == 0 across all members. Alert rules should configure a for: window longer than the Raft election timeout (e.g. for: 30s) to avoid false positives during expected leader transitions. To alert on peer degradation from Prometheus, query hg_raft_alive_peers and on(instance) (hg_raft_leader == 1).

In versions after 1.7.0, PD also exports, for each registered store, hg_store_state{store="<id>",state="<state>"}, which is 1 for the store’s current state (Unknown, Pending, Up, Offline, Exiting or Tombstone) and 0 for the others, and hg_store_leader_count{store="<id>"}, the number of shard groups whose leader is on that store. A rebuilt Store reports 0 leaders until leadership moves back to it. Every PD member reads the same replicated metadata, so select one instance before aggregating these series.

7.6 Store Decommissioning and Drain Lifecycle

Decommissioning a Store node follows a state machine to safely drain partition replicas without service interruption:

  1. State Machine Overview:

    • Up: The Store is online, healthy, and accepting new shard allocations and leader roles.
    • Exiting: The Store is actively draining. While in Exiting, the Store continues renewing its heartbeat lease, but PD excludes it from new replica allocation and partition migration targets.
    • Partition Migration: PD schedules background tasks to migrate all shard replicas off the draining store to other eligible active Stores.
    • Tombstone: The Store is permanently retired. Once marked Tombstone, management updates cannot return the Store to an active state.
  2. Draining Invocation: Initiate store draining via:

    1curl -X POST http://<pd-host>:8620/v1/store/{storeId} \
    2  -H "Authorization: Basic <credentials>" \
    3  -H "Content-Type: application/json" \
    4  -d '{"storeState": "Exiting"}'
  3. Capacity Constraints & Retirement Checks:

    • Capacity Check: Draining checks that remaining eligible active stores satisfy minStoreCount (pd.min-store-count). If remaining capacity is insufficient, PD blocks the transition and rejects the request before state changes. In this case, add eligible Store capacity and resubmit the request.
    • Retirement Criteria: PD keeps the Store in Exiting until its latest heartbeat reports 0 local partition engines AND PD has no remaining shard groups referencing that Store ID.
    • Pre-Deletion Verification: Before deleting the Store Pod or persistent volume, operators must verify remaining shard groups have full Raft membership, complete replicas, and fresh heartbeats.
    • Re-registration Intent Preservation: Re-registering an Exiting Store (e.g. after process restart) preserves the Exiting intent even if its address is in pd.initial-store-list.

3 - HugeGraph-Store Quick Start

1 HugeGraph-Store Overview

HugeGraph-Store is the storage node component of HugeGraph’s distributed version, responsible for actually storing and managing graph data. It works in conjunction with HugeGraph-PD to form HugeGraph’s distributed storage engine, providing high availability and horizontal scalability.

Each Store node keeps graph data in RocksDB and replicates it with Raft (JRaft): every partition is a separate Raft group, so a partition survives the loss of a minority of its replicas. Store nodes do not know about each other directly. They register with PD, receive their partition assignment from PD, and report state back over a heartbeat. HugeGraph-Server reaches Store over gRPC after looking up partition locations in PD.

2 Prerequisites

2.1 Requirements

  • Operating System: Linux or macOS (Windows has not been fully tested)
  • Java version: Java 17 for HugeGraph 1.8.0+ (the Maven build accepts only JDK 17; the start script rejects older runtimes; 1.7.0 is the last release supporting Java 11)
  • Maven version: ≥ 3.6.3 (for building from source)
  • Deploy HugeGraph-PD first for multi-node deployment

3 Deployment

Choose a deployment method for the HugeGraph-Store component:

3.1 Download the tar package

Apache downloads currently provide the complete 1.7.0 binary bundle containing PD, Store, and Server, without a separate Store binary. Verify version, signatures, and SHA512 on the official download page. This historical incubating release retains incubating in archive and directory names:

1# Historical release 1.7.0 retains incubating in filenames and directories
2curl -fLO --connect-timeout 10 --max-time 1800 https://downloads.apache.org/hugegraph/1.7.0/apache-hugegraph-incubating-1.7.0.tar.gz
3tar zxf apache-hugegraph-incubating-1.7.0.tar.gz
4cd apache-hugegraph-incubating-1.7.0/apache-hugegraph-store-incubating-1.7.0

3.2 Compile from source

  1. Clone the source code:

    1git clone https://github.com/apache/hugegraph.git
    2cd hugegraph
  2. Build dependent struct and Store module:

    1# Build hugegraph-struct dependency and Store distribution
    2mvn install -pl hugegraph-struct -am -DskipTests
    3mvn clean package -pl hugegraph-store/hg-store-dist -am -DskipTests
  3. Locate the distribution output:

    1cd hugegraph-store/apache-hugegraph-store-*
    2ls -la bin conf lib

The assembled directory contains only bin/, conf/ and lib/hg-store-node-{version}.jar.

3.3 Docker Deployment

HG_STORE_* mappings are current master features, absent from Server tag 1.7.0. These Docker examples require PD, Store, and HStore Server images built from the same current master source with matching local tags:

1# Run from the HugeGraph repository root
2docker build -f hugegraph-pd/Dockerfile -t hugegraph/pd:local .
3docker build -f hugegraph-store/Dockerfile -t hugegraph/store:local .
4docker build -f hugegraph-server/Dockerfile-hstore -t hugegraph/server:local .

Before first startup, create .env in docker/ following the authentication environment instructions. The procedure uses umask 077 and refuses to overwrite existing files. Keep an existing .env and add missing entries. Never regenerate HG_PD_AUTH_SECRET_KEY for initialized data directories. Although .gitignore excludes this file, do not commit it. In every new shell, load the same file from docker/ before Compose or PD REST commands:

1# Run from the HugeGraph repository root
2cd docker
3set -a; . ./.env; set +a
4: "${HG_PD_AUTH_SECRET_KEY:?Set HG_PD_AUTH_SECRET_KEY in .env}"
5# Start PD, Store, and Server without optional Hubble
6HUGEGRAPH_VERSION=local HUGEGRAPH_PULL_POLICY=never \
7  docker compose -f docker-compose-hstore.yml \
8  up -d --wait pd store server

Load the same secret before subsequent restarts or PD REST calls; do not regenerate it for initialized directories. Explicitly include HUGEGRAPH_VERSION=local and HUGEGRAPH_PULL_POLICY=never in every Compose lifecycle command.

To start Hubble, use the topology-specific untracked configuration: minimal docker-compose-hstore.yml mounts conf/hubble/hstore.local.properties; HA docker-compose-3pd-3store-3server.yml mounts conf/hubble/hstore-ha.local.properties. The README initialization creates both files with the shared PD secret. If missing or requiring updates, load existing .env from docker/ and run:

1set -a; . ./.env; set +a
2./set-hubble-pd-password.sh hstore      # Minimal topology
3./set-hubble-pd-password.sh hstore-ha  # HA topology

Multi-node service names are pd0–pd2, store0–store2, and server0–server2. This master Compose file also requires matching locally built images; do not mix HUGEGRAPH_VERSION=1.7.0 release images with master Compose.

To run master-built Store alone, replace example addresses with actual routable Store and PD addresses:

The mkdir -p and nonrecursive chown below are for a new empty directory. Before reusing data written by a root image, stop Store and run sudo chown -R 10001:10001 /path/to/storage once, then start the UID 10001 image.

 1# Master-built images run as UID 10001; the host data directory must be writable by it
 2mkdir -p /path/to/storage && sudo chown 10001:10001 /path/to/storage
 3docker run -d \
 4  -p 8520:8520 -p 8500:8500 -p 8510:8510 \
 5  -e HG_STORE_PD_ADDRESS=192.168.1.10:8686 \
 6  -e HG_STORE_GRPC_HOST=192.168.1.20 \
 7  -e HG_STORE_RAFT_ADDRESS=192.168.1.20:8510 \
 8  -v /path/to/storage:/hugegraph-store/storage \
 9  --name hugegraph-store \
10  hugegraph/store:local

Current Master Docker Environment Variables:

VariableRequiredDefaultConfiguration keyDescription
HG_STORE_PD_ADDRESSYesNonepdserver.addressComma-separated PD gRPC addresses.
HG_STORE_GRPC_HOSTYesNonegrpc.hostAdvertised hostname/IP; use a container hostname within a container network.
HG_STORE_RAFT_ADDRESSYesNoneraft.addressThis node’s Raft address.
HG_STORE_GRPC_PORTNo8500grpc.portgRPC service port.
HG_STORE_REST_PORTNo8520server.portREST API port.
HG_STORE_DATA_PATHNo/hugegraph-store/storageapp.data-pathData path.
HG_STORE_ROCKSDB_TOTAL_MEMORY_SIZENoNonerocksdb.total_memory_sizeRocksDB memory budget: auto or a number of bytes. An empty value counts as unset; any other value makes the entrypoint exit with code 2. When unset, the value in application-pd.yml or auto-sizing applies.

The master entrypoint writes these values into SPRING_APPLICATION_JSON, overriding image conf/application.yml. Other options still come from that file and application-pd.yml; Java runs in the foreground. Deprecated PD_ADDRESS, GRPC_HOST, and RAFT_ADDRESS remain supported with warnings.

PD and Store Docker HEALTHCHECK use /v1/health, confirming only local REST responses. Compose depends_on uses the same startup gate; separately verify PD /v1/ready and Up Store state in /v1/stores. Store defaults to STDOUT_MODE=true; its Dockerfile declares only EXPOSE 8520, so publish gRPC 8500 and Raft 8510 separately if needed outside the Docker network.

4 Configuration

Store reads two files under conf/. Release 1.7.0 sources: application.yml, application-pd.yml. Master sources: application.yml, application-pd.yml. Master places RocksDB settings in the second file, included through spring.profiles.include: pd; startup selects application.yml.

  • application.yml: Main PD address, ports, Raft, and data path settings.
  • application-pd.yml: Included through spring.profiles.include: pd; RocksDB memory and Actuator exposure.

4.1 application.yml

The following tables were checked against distribution values and Java defaults at Server master. Use tagged configuration for release 1.7.0 without replacing it with another version’s files.

4.2 application-pd.yml

This file contains only rocksdb and Actuator exposure settings.

Warning

Protect Server and Store ports separately in production

Enable Server authentication and authorization, an IP allowlist, and minimum graph API permissions; retain and protect Server audit-*.log. These settings do not protect Store: master exposes all Actuator endpoints without PD-style Basic authentication. Restrict Store REST, gRPC, and Raft to cluster nodes and trusted operations networks.

4.3 Configuration reference

“Master distribution value” comes from the two master files above. “Code default” is the fallback when a key is absent; rely on code defaults for options omitted from the distribution files.

Core

KeyMaster distribution valueCode defaultMeaning
pdserver.addresslocalhost:8686requiredPD gRPC endpoints, comma separated. Store registers itself here and receives its partition assignment. Must be PD’s grpc.port, not its REST port.
grpc.host127.0.0.1requiredAddress this node advertises for its own gRPC service. Set it to a routable IP or hostname, 127.0.0.1 is only usable for a single-machine setup.
grpc.port8500requiredgRPC port. Server and the Store client connect here.
grpc.netty-server.max-inbound-message-size1000MBgRPC defaultMaximum size of a single inbound gRPC message. Bound by the grpc-spring-boot-starter Netty server.
grpc.server.wait-timenot set3600Seconds a scan stream waits for the client to consume a page before the server aborts it.
server.port8520requiredREST and Actuator port. Also reported to PD as the rest.port label.

Raft

KeyMaster distribution valueCode defaultMeaning
raft.address127.0.0.1:8510requiredRaft service address of this node, host:port. Must be reachable from every other Store node. There is no peer list to configure: PD tells each node which peers belong to a partition’s Raft group.
raft.disruptorBufferSize10240Raft task queue size. 0 derives it from rocksdb.total_memory_size, by rounding that size in GB (at least 1) to the nearest power of two and multiplying by 32.
raft.max-log-file-size60000000000050000000000Maximum byte size of Raft logs.
raft.snapshotInterval1800300Seconds between Raft snapshots.
raft.snapshotLogIndexMarginnot set0Minimum applied-index distance since the last snapshot before a snapshot is actually written. 0 disables the distance check.
raft.rpc-timeoutnot set10000Raft RPC timeout in milliseconds.
raft.metricsnot settrueCollect JRaft node metrics, readable at /metrics/raft.
raft.useRocksDBSegmentLogStoragenot settrueStore Raft logs in the RocksDB segment log storage.
raft.maxSegmentFileSizenot set67108864Segment log file size in bytes (64 MB).
raft.maxReplicatorInflightMsgsnot set256Maximum in-flight replication requests per follower.
raft.maxEntriesSizenot set256Maximum number of entries in one AppendEntries request.
raft.maxBodySizenot set524288Maximum byte size of one AppendEntries request.
ave-logEntry-size-rationot set0.95Smoothing ratio used to estimate the average log entry size. Note that this key sits at the top level, not under raft.

Storage and labels

KeyMaster distribution valueCode defaultMeaning
app.data-path./storagestoreRocksDB data directory. Multiple paths separated by commas spread partitions over several disks.
app.raft-pathcommented outemptyDirectory for Raft logs and snapshots. Falls back to app.data-path when empty.
app.fake-pdnot setfalseBuilt-in PD mode for standalone testing. Do not use it in production.
app.placeholder-sizenot set10Size in GB of a placeholder file created in each data path at startup, so space can be freed in an emergency. 0 disables it.
app.label.<name>not setnoneArbitrary key/value labels sent to PD in the store heartbeat. The node adds rest.port on its own.

RocksDB

KeyMaster distribution valueCode defaultMeaning
rocksdb.total_memory_sizeautoAuto-sized, see noteOff-heap memory budget shared across all RocksDB instances on this node (auto or byte count). See below for derivation rules.
rocksdb.write_buffer_size32000000Derived, see MeaningMemtable size in bytes. When absent or 0, the node uses total_memory_size / 1000, at least 1048576 (1 MiB).
rocksdb.min_write_buffer_number_to_merge1616Number of memtables merged together before a flush.
rocksdb.write_buffer_rationot set0.66Share of total_memory_size given to the write cache. The rest becomes the block cache.

RocksDB memory budget sizing rules

Note

When rocksdb.total_memory_size is set to auto (or absent / 0), the node sizes the off-heap RocksDB budget automatically:

  • Calculation Formula: Takes physical memory (using the visible cgroup limit in containers) minus JVM maximum heap (-Xmx), direct memory (MaxDirectMemorySize), and a 1.5 GiB system reserve, then allocates half the remainder, clamped between 256 MiB and 32 GB (32000000000 bytes).
  • Write Cache & Block Cache: Budget is divided according to rocksdb.write_buffer_ratio (default 0.66). This is a soft capacity target; under heavy concurrent write loads, set rocksdb.write_buffer_allow_stall to true to hold the write cache to its share at the cost of write latency. The block cache is not a strict limit, so native memory can still exceed the budget and a container can still be OOM-killed.
  • Upgrading Existing Deployments: Deployments carrying legacy 32000000000 can enable auto-sizing by setting environment variable HG_STORE_ROCKSDB_TOTAL_MEMORY_SIZE=auto or JVM property -Drocksdb.total_memory_size=auto.

Any other option defined in org/apache/hugegraph/rocksdb/access/RocksDBOptions.java can be added under the same rocksdb: block, for example rocksdb.max_background_jobs, rocksdb.level0_file_num_compaction_trigger or rocksdb.bloom_filter_bits_per_key.

Thread pools

KeyCode defaultMeaning
thread.pool.grpc.core600Core threads serving gRPC requests.
thread.pool.grpc.max1000Maximum gRPC threads.
thread.pool.grpc.queue2147483647gRPC task queue capacity.
thread.pool.scan.core128Core threads serving scans. 0 means 4 times the CPU count.
thread.pool.scan.max1000Maximum scan threads.
thread.pool.scan.queue0Scan task queue capacity.

gRPC callback queue (1.8.0)

Store uses an unbounded queue for gRPC callbacks so that a full queue does not discard cancellation or completion notifications and leave requests unfinished. You can keep thread.pool.grpc.queue in the configuration, but it no longer limits this queue.

thread.pool.grpc.core and thread.pool.grpc.max still configure the thread pool. Because callbacks can continue to queue, a backlog normally does not grow the pool from core to max; increasing max alone does not increase callback processing capacity.

Sustained overload can still grow the queue and increase memory usage. Limit client concurrency and size the scan and query worker pools for the node’s resources; do not rely on thread.pool.grpc.queue for load control. Version 1.7.0 still uses the configured gRPC queue capacity.

Query pushdown

KeyCode defaultMeaning
query.push-down.threads1500Thread pool size for pushed-down queries.
query.push-down.fetch_batch20000Rows fetched per request.
query.push-down.fetch_timeout300000Fetch timeout in milliseconds.
query.push-down.memory_limit_count50000Row limit for in-memory operations such as sorting.
query.push-down.index_size_limit_count50000Index sst file size limit in kB.

Background jobs

KeyCode defaultMeaning
job.interruptableThreadPool.core128Core threads of the TTL cleaner pool. 0 means the CPU count.
job.interruptableThreadPool.max256Maximum threads of the TTL cleaner pool. 0 means 4 times the CPU count.
job.interruptableThreadPool.queue2147483647Queue capacity of the TTL cleaner pool.
job.uninterruptibleThreadPool.core0Core threads of the engine’s uninterruptible job pool. 0 means the CPU count.
job.uninterruptibleThreadPool.max256Maximum threads of the uninterruptible job pool.
job.uninterruptibleThreadPool.queue2147483647Queue capacity of the uninterruptible job pool.
job.cleaner.batch.size10000Keys deleted per batch by the TTL cleaner.
job.start-time0Hour of day (0 to 23) at which the daily TTL cleanup runs. Values outside that range fall back to 19.

Built-in PD mode

Only for single-node development and debugging, activated by app.fake-pd: true. The node then plays PD’s role itself and ignores pdserver.address.

KeyCode defaultMeaning
fake-pd.store-list''gRPC addresses of the Store nodes in the fake cluster.
fake-pd.peers-list''Raft addresses of the same nodes.
fake-pd.partition-count3Number of partitions.
fake-pd.shard-count3Replicas per partition.

Diagnostics

Starting with HugeGraph 1.8.0, Store HTTP activation (GET /v1/arthasstart) is disabled and returns 403. Legacy configuration fields are kept only for compatibility. Run the bundled script as the service OS user on the host to diagnose the running JVM (official container images include JDK 17):

1bin/arthas.sh

For multiple processes on one host, specify --pid <PID> --telnet-port 3659. For command options, authentication, and security practices, see Start the Arthas agent.

4.4 Per-node changes

For multi-node deployment, you need to modify the following configurations for each Store node:

  1. grpc.host and grpc.port (the address other components dial)
  2. raft.address (Raft protocol address)
  3. server.port (REST port)
  4. app.data-path (data storage path)

pdserver.address is the same on every node, it lists the whole PD cluster.

5 Start and Stop

5.1 Start Store

Ensure that the PD service is already started, then in the Store installation directory, execute:

1./bin/start-hugegraph-store.sh

The lifecycle and timeout details below describe master builds that include launcher script repairs. The downloaded 1.7.0 launcher does not include those repairs. The script accepts four flags, with GC version limits noted below:

FlagValuesDefaultDescription
-dtrue, falsetrueDaemon mode. See below.
-gSee version limits belownot setSelect the garbage collector. Unsupported values abort startup.
-jJVM options stringemptyExtra JVM options, for example -j "-Xmx16g -Xms8g".
-ytrue, falsefalseAttach the OpenTelemetry Java agent, downloading it into plugins/ on first use, and export traces to 127.0.0.1:4317.

Master builds accept g1, G1, zgc and ZGC. The downloaded 1.7.0 launcher accepts only zgc or ZGC as explicit choices; -g g1, -g G1 and other values abort startup. Omit -g for the default path. For rejected values, inspect logs/hugegraph-store-server.log.

Daemon mode:

  • -d true (default): run as a background daemon. The script returns immediately and writes the Java pid to bin/pid.
  • -d false: run in the foreground. The script execs Java, so the container or supervisor process is Java itself. Use this under Docker or a process supervisor (systemd, supervisord) so crashes are detected and the service is restarted automatically.

JVM memory, unless you set JAVA_OPTIONS yourself: -Xms512m, and -Xmx set to half the free memory, clamped to the 512 MB to 2048 MB range. The script also adds -XX:MaxDirectMemorySize equal to that heap, -XX:MetaspaceSize=256M, a heap dump on out-of-memory into logs/, and a rolling GC log at logs/gc.log. Production nodes normally need a much larger heap, so pass one explicitly together with a direct-memory cap, for example -j "-Xmx32g -Xms32g -XX:MaxDirectMemorySize=2g". Without the cap the JVM allows as much direct memory as the 32 GB heap, the RocksDB budget counts it, and on a host with less than about 66 GB it falls to the 256 MiB floor.

The script refuses to start if ulimit -n or ulimit -u is below 1024, and it preloads jemalloc on x86_64 and arm64 when the shared object can be downloaded and verified.

In master builds, each optional jemalloc download allows 5 seconds to connect and 30 seconds in total. The 1.7.0 helper has no connection or total timeout. A timeout or failed verification follows the existing fallback: startup continues without preloading the downloaded library. Verified cached libraries can still be reused; partial downloads are removed.

After successful startup, you can see logs similar to the following in logs/hugegraph-store-server.log:

1YYYY-mm-dd xx:xx:xx [main] [INFO] o.a.h.s.n.StoreNodeApplication - Started StoreNodeApplication in x.xxx seconds (JVM running for x.xxx)

5.2 Stop Store

In the Store installation directory, execute:

1./bin/stop-hugegraph-store.sh

The script reads bin/pid, signals that process, and waits up to 30 seconds for it to exit before removing the pid file. If bin/pid is missing it exits without doing anything.

5.3 Restart Store

1./bin/restart-hugegraph-store.sh

It sources the stop script and then the start script, and forwards the flags from section 5.1.

5.4 Startup order

  1. All PD nodes first. Each Store’s grpc.host:grpc.port must appear in PD pd.initial-store-list, or the node remains Pending instead of Up, blocking partition allocation. On master, verify HTTP 200 with ready:true from every PD /v1/ready first; /v1/health is liveness only.
  2. Store next. Registration retries while PD is unreachable, logging store heartbeat error: PD UNREACHABLE.
  3. Server last. Every Store should report Up; partitions must be ready before opening or initializing graphs.

Master Compose uses depends_on: condition: service_healthy for local liveness, but PD and Store Docker checks only call /v1/health; they do not confirm Raft quorum or Store registration. Server waits for PD to report at least one Up Store. Operators should still check PD /v1/ready and /v1/stores.

6 Multi-Node Deployment Example

Below is a configuration example for a three-node deployment:

6.1 Three-Node Configuration Reference

  • 3 PD nodes
    • raft ports: 8610, 8611, 8612
    • rpc ports: 8686, 8687, 8688
    • rest ports: 8620, 8621, 8622
  • 3 Store nodes
    • raft ports: 8510, 8511, 8512
    • rpc ports: 8500, 8501, 8502
    • rest ports: 8520, 8521, 8522

6.2 Store Node Configuration

For the three Store nodes, the main configuration differences are as follows:

Node A:

1grpc:
2  port: 8500
3raft:
4  address: 127.0.0.1:8510
5server:
6  port: 8520
7app:
8  data-path: ./storage-a

Node B:

1grpc:
2  port: 8501
3raft:
4  address: 127.0.0.1:8511
5server:
6  port: 8521
7app:
8  data-path: ./storage-b

Node C:

1grpc:
2  port: 8502
3raft:
4  address: 127.0.0.1:8512
5server:
6  port: 8522
7app:
8  data-path: ./storage-c

All nodes should point to the same PD cluster:

1pdserver:
2  address: 127.0.0.1:8686,127.0.0.1:8687,127.0.0.1:8688

And every PD node should list all three Store gRPC addresses:

1pd:
2  initial-store-list: 127.0.0.1:8500,127.0.0.1:8501,127.0.0.1:8502

6.3 Docker Distributed Cluster Configuration

The distributed Store cluster definition is included in docker/docker-compose-3pd-3store-3server.yml. Each Store node gets its own hostname and environment variables:

 1# store0, published as 8500 (gRPC), 8510 (Raft), 8520 (REST)
 2HG_STORE_PD_ADDRESS: pd0:8686,pd1:8686,pd2:8686
 3HG_STORE_GRPC_HOST: store0
 4HG_STORE_GRPC_PORT: "8500"
 5HG_STORE_REST_PORT: "8520"
 6HG_STORE_RAFT_ADDRESS: store0:8510
 7HG_STORE_DATA_PATH: /hugegraph-store/storage
 8
 9# store1, published as 8501, 8511, 8521
10HG_STORE_GRPC_HOST: store1
11HG_STORE_RAFT_ADDRESS: store1:8510
12
13# store2, published as 8502, 8512, 8522
14HG_STORE_GRPC_HOST: store2
15HG_STORE_RAFT_ADDRESS: store2:8510

The container ports stay 8500/8510/8520 on every node, only the published host ports differ. The PD nodes set HG_PD_INITIAL_STORE_LIST: store0:8500,store1:8500,store2:8500 to match.

Store nodes start only after all PD nodes pass healthchecks (/v1/health), enforced via depends_on: condition: service_healthy.

To view runtime logs for a running Store container use docker logs <container-name> (e.g. docker logs hg-store0).

See docker/README.md for the full setup guide.

7 Verify Store Service

Confirm that the Store service is running properly:

1curl http://localhost:8520/actuator/health

Actuator {"status":"UP"} confirms local Store application health, without proving registration as Up in PD.

GET /v1/health is the lighter check used by the Docker image and the compose files. It answers HTTP 200 with an empty body, so use curl -fsS and check the exit code rather than the output:

1curl -fsS http://localhost:8520/v1/health && echo OK

7.1 Store REST endpoints

The Store node exposes these read-only endpoints on server.port:

MethodPathDescription
GET/v1/healthLiveness probe, HTTP 200 with an empty body
GET/actuator/healthSpring Boot Actuator health, {"status":"UP"}
GET/actuator/prometheusPrometheus scrape endpoint
GET/Node summary, leaderCount and partitionCount
GET/-/stateOperator-set STARTING, ONLINE, or STOPPING flag; distinct from PD registration state
GET/-/lifecycleProcess lifecycle state (available in 1.8.0+)
GET/-/echo?name=<text>Echo check
GET/-/scanState of the running scan streams
GET/v1/partitionsAll Raft groups on this node with per-partition metrics. Add ?flags=accurate for exact key counts, which is slower.
GET/v1/partition/{id}One Raft group by partition id, including role, leader, peers and committed index
GET/metrics/systemHost CPU and memory metrics
GET/metrics/driveDisk metrics for the data paths
GET/metrics/raftJRaft node metrics, needs raft.metrics: true

GET /-/lifecycle reports the process lifecycle status as JSON, such as {"status":0,"text":"STARTED"}. The text field has four possible values:

  • STARTING: Spring application context or gRPC service is still initializing;
  • STARTED: Spring application is ready (ApplicationReadyEvent) and gRPC service is running;
  • STOPPING: Process shutdown has initiated (ContextClosedEvent takes precedence);
  • UNAVAILABLE: gRPC service stopped or terminated unexpectedly before shutdown.
Warning

Process lifecycle does not equal cluster readiness: STARTED reflects only local JVM and gRPC process state, not storage or cluster data readiness. It does not prove that the node has registered with PD, that data shards have completed recovery, or that Raft replicas have caught up.

  • Before continuing a rolling update or replacing nodes, always check PD via GET /v1/stores to confirm the store status is Up, and inspect GET /v1/partitions to ensure all Raft groups are healthy. Never rely solely on STARTED as a rolling update gate.
  • Versions prior to 1.8.0 do not support this endpoint and return HTTP 404; a 404 must not be treated as STARTED.

Master Store configuration exposes all Actuator endpoints with management.endpoints.web.exposure.include: "*" and enables Prometheus. These endpoints lack PD REST Basic protection; restrict Store REST network access.

The node also serves maintenance endpoints that change state or run heavy work: PUT /-/state, GET /-/cleaner, GET /v1/partition/dump/{id}, GET /v1/partition/clean/{id}, POST /v1/compat?id=<partition>, POST /raft/options, and the /fix/* and /test/* groups. Use them only for troubleshooting, and keep the REST port off untrusted networks.

7.2 Check registration from PD

You can also check Store node status through the PD API:

1curl -u "store:${HG_PD_AUTH_SECRET_KEY:?Set the PD deployment secret first}" \
2  http://localhost:8620/v1/stores

For master builds, PD REST usernames must be hg, store, hubble, or vermeer, and the password must equal PD auth.secret-key. HG_PD_AUTH_SECRET_KEY configures PD and Server in Compose. /v1/health, /v1/ready, /actuator/*, and /v1/prom/targets/* require no authentication. Release 1.7.0 checks only usernames, without comparing passwords; do not use that old behavior for master builds.

If Store is configured successfully, the response should include status information for the current node, and state: "Up" means the node is running normally. A node stuck at Pending is usually missing from PD’s pd.initial-store-list.

The example below shows a single Store node. If all three nodes are configured correctly and running, the storeId list should contain three IDs, and stateCountMap.Up, numOfService, and numOfNormalService should all be 3.

 1{
 2  "message": "OK",
 3  "data": {
 4    "stores": [
 5      {
 6        "storeId": 8319292642220586694,
 7        "address": "127.0.0.1:8500",
 8        "raftAddress": "127.0.0.1:8510",
 9        "version": "",
10        "state": "Up",
11        "deployPath": "/Users/{your_user_name}/hugegraph/hugegraph-store/apache-hugegraph-store-{version}/lib/hg-store-node-{version}.jar",
12        "dataPath": "./storage",
13        "startTimeStamp": 1754027127969,
14        "registedTimeStamp": 1754027127969,
15        "lastHeartBeat": 1754027909444,
16        "capacity": 494384795648,
17        "available": 346535829504,
18        "partitionCount": 0,
19        "graphSize": 0,
20        "keyCount": 0,
21        "leaderCount": 0,
22        "serviceName": "127.0.0.1:8500-store",
23        "serviceVersion": "",
24        "serviceCreatedTimeStamp": 1754027127000,
25        "partitions": []
26      }
27    ],
28    "stateCountMap": {
29      "Up": 1
30    },
31    "numOfService": 1,
32    "numOfNormalService": 1
33  },
34  "status": 0
35}

7.3 Minimal Graph Read/Write Verification

After Store appears as Up in PD, start an HStore-backed Server connected to the same PD cluster. See the Server Quick Start. Once GET /versions responds and the default hugegraph graph is loaded, create a property key, vertex label, and vertex, then read it:

 1SERVER_URL=http://localhost:8080
 2GRAPH_URL="$SERVER_URL/graphspaces/DEFAULT/graphs/hugegraph"
 3
 4# Names must be unique within the graphspace; choose new names if they already exist
 5curl -fsS -X POST "$GRAPH_URL/schema/propertykeys" \
 6  -H 'Content-Type: application/json' \
 7  -d '{"name":"pd_store_demo_name","data_type":"TEXT","cardinality":"SINGLE","properties":[]}'
 8
 9curl -fsS -X POST "$GRAPH_URL/schema/vertexlabels" \
10  -H 'Content-Type: application/json' \
11  -d '{"name":"pd_store_demo_vertex","id_strategy":"CUSTOMIZE_STRING","properties":["pd_store_demo_name"],"primary_keys":[],"nullable_keys":[]}'
12
13curl -fsS -X POST "$GRAPH_URL/graph/vertices" \
14  -H 'Content-Type: application/json' \
15  -d '{"id":"pd-store-demo-1","label":"pd_store_demo_vertex","properties":{"pd_store_demo_name":"stored in HStore"}}'
16
17curl -fsS "$GRAPH_URL/graph/vertices/%22pd-store-demo-1%22"

The final response should contain vertex ID pd-store-demo-1 and property pd_store_demo_name. If Server authentication is enabled, add credentials to each request.

4 - Deploy HugeGraph with Helm

This guide covers HugeGraph 1.8.0 and later, using Helm 3.10+ with OCI support and Kubernetes (K8s) 1.23+. Install hugegraph-helm from GHCR or Docker Hub. Chart and HugeGraph versions are maintained separately: for example, a 0.4.x Chart can deploy a 1.8.x service.

Warning

The current development Chart uses latest images for the base HugeGraph components and is intended for testing. Optional Vermeer is pinned to a verified published image and digest; see optional engines. For production, choose a stable Chart once the corresponding HugeGraph service has been released, and review its image versions. Image tags can change; set each component’s image.digest to keep using the same image content.

Artifact Hub helps you find the Chart, browse versions and read installation instructions. The packages themselves are downloaded from GHCR or Docker Hub. See the chart README for settings and source-based development, and the operations reference for lifecycle procedures.

Find a Chart version on Artifact Hub, download from GHCR or Docker Hub, and install with Helm

1 Install

Note

Default Topology & Storage Prerequisites

  • Components: Deploys 3 PD + 3 Store + 3 Server and Hubble by default, with authentication and persistent storage enabled.
  • Volume Requirements: Requires a default dynamic StorageClass or matching pre-created static PVs, totaling 7 persistent volumes (3 × 10 GiB PD volumes, 3 × 50 GiB Store volumes, and 1 × 1 GiB Hubble volume).
  • Memory Sizing: Retains container JVM memory auto-calculation; configure resource requests/limits to allocate sufficient physical memory for the 9 JVMs and Hubble.

Choose either registry; GHCR is recommended for public CI. For local lightweight testing, use the single-node preset.

Tip

--devel selects the highest Chart version, including development and stable versions, without limiting the version series. For production or reproducible installations, replace --devel with --version <published-version> to pin your chosen version.

GHCR (recommended)
1CHART=oci://ghcr.io/hugegraph/hugegraph-helm
2kubectl config current-context
3kubectl get nodes
4kubectl get storageclass
5helm install hugegraph "$CHART" --devel -n hugegraph \
6  --create-namespace --wait --timeout 15m
Docker Hub
1CHART=oci://registry-1.docker.io/hugegraph/hugegraph-helm
2kubectl config current-context
3kubectl get nodes
4kubectl get storageclass
5helm install hugegraph "$CHART" --devel -n hugegraph \
6  --create-namespace --wait --timeout 15m
Single-node trial
1# For local testing (Minikube, Kind): install the Chart downloaded below
2CHART=oci://ghcr.io/hugegraph/hugegraph-helm
3helm pull "$CHART" --devel --untar
4helm install hugegraph ./hugegraph-helm -n hugegraph \
5  -f ./hugegraph-helm/values-single.yaml \
6  --create-namespace --wait --timeout 10m

The single-node preset selects 1 PD + 1 Store + 1 Server using HStore, plus Hubble, with relaxed scheduling constraints. It leaves SeaTunnel and Vermeer disabled.

2 Modes and entry points

The extracted package is rooted at hugegraph-helm/; the source directory remains helm/hugegraph/.

HugeGraph Helm Chart Layout

  • hugegraph-helm/
    • Chart.yamlChart metadata and version definitions
    • values.yamlDefault values (easy mode: 3 PD + 3 Store + 3 Server + 1 Hubble, NodePort)
    • values-single.yamlSingle-node preset (local Minikube/Kind testing with 1 replica and no anti-affinity)
    • values-cluster.yamlMulti-node cluster preset (required anti-affinity, Store OnDelete rollout)
    • values-strict.yamlHardened security preset (strict mode: ClusterIP only, strict NetworkPolicies)
    • values.schema.jsonSchema validation for values configuration
    • templates/Kubernetes workload templates
      • pd-statefulset.yamlPD StatefulSet (metadata and scheduling)
      • store-statefulset.yamlStore StatefulSet (storage engine)
      • server-deployment.yamlServer Deployment (injects serviceId and graphSpace)
      • hubble-deployment.yamlHubble UI Deployment
      • tests/Smoke validation hook (helm test, supports custom testGraphAlias)
    • examples/Deployment examples: local PVs, GitOps credentials, optional engines and Ingress
    • docs/operations.mdLifecycle operations and recovery guide

mode: easy is the default. Server and Hubble use automatic NodePorts; PD stays ClusterIP. HTTP works without a domain, certificate or acknowledgement. mode: strict defaults Server/Hubble to ClusterIP and enables full NetworkPolicy isolation. Enabled SeaTunnel and Vermeer native HTTP/UI default to NodePort in easy mode and ClusterIP in strict mode; both require login. Internal RPC, Worker HTTP and SeaTunnel member ports remain private. Both modes keep authentication and persistence. Explicit component parameters take priority over global parameters, which take priority over mode defaults; explicit false remains an override. The global parameters are persistence.enabled and global.imageRegistry. Strict mode is also available through values-strict.yaml.

EntryAccessRequirements
NodePorthttp://<reachable-node-ip>:<assigned-node-port>Node connectivity and firewall access; no additional controller
ClusterIPInternal Service IP/DNS, for example hugegraph-server.hugegraph.svc:8080External clients use port-forward or an existing gateway
LoadBalancerInfrastructure-assigned addressCompatible load balancer controller
IngressHTTP routing through a controllerInstalled controller; hostname and TLS optional
1kubectl -n hugegraph get svc hugegraph-server hugegraph-hubble
2kubectl get nodes -o wide
3kubectl -n hugegraph get secret hugegraph-admin \
4  -o jsonpath='{.data.password}' | base64 --decode

Open Hubble on its assigned NodePort and log in as admin with this password. A node need not host the Pod with default externalTrafficPolicy: Cluster. The internal ClusterIP is a virtual Service address, not a node IP; a laptop normally cannot reach it directly. Use kubectl -n hugegraph port-forward svc/hugegraph-hubble 8088:8088 for a local browser at http://127.0.0.1:8088.

The base PD/Server/Hubble client Services support externalTrafficPolicy, loadBalancerClass, loadBalancerIP, loadBalancerSourceRanges, externalIPs and allocateLoadBalancerNodePorts, subject to the cluster/controller’s capabilities. Use LoadBalancer fields with that Service type. NodePort omission or 0 means automatic allocation. Fixed ports are validated against the cluster’s configured range by Kubernetes; the chart does not force 30000–32767. Legacy HTTP acknowledgement fields remain accepted but no longer gate rendering.

Optional engines: disabled by default

By default, the Chart provisions only the core graph services (PD + Store + Server + Hubble). For data migration and distributed memory graph computing, the Chart offers SeaTunnel and Vermeer as native optional engines, both disabled by default:

EngineDefaultPurposeTopologies (*.mode)Access & Security
HubbleEnabled (true)Graph visualization, multi-graphspace management & metricsSingle-replica DeploymentFollows global mode (NodePort or ClusterIP)
SeaTunnelDisabled (false)Heterogeneous data ingestion & full graph migrationstandalone / clusterNodePort in easy, ClusterIP in strict; HTTP Basic auth
VermeerDisabled (false)Memory-first high-performance distributed graph algorithmsstandalone / clusterNodePort in easy, ClusterIP in strict; Token auth, auto-wired to Hubble

Enable either engine by setting its enabled key to true in values. Their administrator passwords are generated independently from Server. For seatunnel.service.type and vermeer.service.type, null inherits the mode default: NodePort in easy mode, ClusterIP in strict mode. An explicit ClusterIP stays private; an explicit NodePort, including in strict mode, exposes authenticated HTTP/UI. Clear an older explicit ClusterIP override to null to inherit easy mode. With service.nodePort omitted or null, Kubernetes assigns the port. The engines’ standalone / cluster topologies are independent of these access settings.

SeaTunnel: On-demand Data Import, Export, and Migration
1helm install hugegraph ./hugegraph-helm -n hugegraph --create-namespace \
2  -f ./hugegraph-helm/values-single.yaml \
3  --set seatunnel.enabled=true --set seatunnel.mode=standalone \
4  --wait --timeout 30m
  • Topologies: standalone runs 1 Hybrid node for lightweight testing; cluster runs multiple homogeneous nodes for high-throughput batch jobs.

  • Access & Authentication: In easy mode, open http://<reachable-node-ip>:<NodePort>/#/overview using the assigned HTTP NodePort:

    1kubectl -n hugegraph get svc hugegraph-seatunnel \
    2  -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}{"\n"}'
    3kubectl get nodes -o wide

    Log in with HTTP Basic username admin and the password from hugegraph-seatunnel-auth Secret. Strict mode defaults to ClusterIP; use kubectl -n hugegraph port-forward svc/hugegraph-seatunnel 8081:8080 for local access. Port 5801 remains internal.

  • See the SeaTunnel Deployment Section or SeaTunnel Guide for full job configs and migration steps.

Vermeer: In-Memory Graph Computing Integrated with Hubble
1helm install hugegraph ./hugegraph-helm -n hugegraph --create-namespace \
2  -f ./hugegraph-helm/values-single.yaml \
3  --set vermeer.enabled=true --set vermeer.mode=standalone \
4  --wait --timeout 20m
1hugegraph-helm/
2  examples/
3    values-vermeer-standalone.yaml # Standalone preset (Master and Worker combined in one Pod)
4    values-vermeer-cluster.yaml    # Cluster preset (1 dedicated Master Pod + 3 distributed Worker Pods)
5  docs/
6    vermeer.md                     # Advanced algorithm parameters, API mapping and operations
  • Topologies: standalone runs Master and Worker in one Pod; cluster provides a separate Master coordinator Pod and scalable Worker computing Pods (default 3 replicas).

  • Hubble Integration: Hubble automatically acquires the internal Master Service URL and service tokens. Operators can trigger 15+ graph algorithms directly from Hubble without manual token configuration.

  • Native Dashboard Access: In easy mode, open http://<reachable-node-ip>:<NodePort>/ using the Master HTTP NodePort:

    1kubectl -n hugegraph get svc hugegraph-vermeer-master \
    2  -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}{"\n"}'
    3kubectl get nodes -o wide

    Sign in with the password from Secret <release>-vermeer-admin under Admin credential. Strict mode defaults to ClusterIP; use kubectl -n hugegraph port-forward svc/hugegraph-vermeer-master 6688:6688 for local access. Master/Worker RPC and Worker HTTP remain internal.

  • For image pinning and credentials management, see the Vermeer Deployment Guide.

PD metadata namespace

The top-level metadataCluster parameter (default hg-test) specifies the PD metadata cluster prefix. The Chart injects this value into Server HG_SERVER_CLUSTER and Store PD_CLUSTER, ensuring Store correctly locates the Schema initialized by Server when processing Vermeer graph scans.

Important

metadataCluster is a metadata namespace prefix, not a Raft group name. Modifying it does not automatically migrate existing graph data. Always preserve the original cluster prefix when enabling Vermeer; if graph load tasks fail with Schema missing or no such vertex label, check that the namespace prefix matches across all components. Refer to the Metadata Namespace Operations Guide for details. Standard older releases using hg-test need no namespace-adoption step. For a custom legacy prefix, follow metadata namespace adoption before upgrading.

Server service identity and graph space

Both server.serviceId and server.graphSpace default to DEFAULT. To register the Server with a specific service name or graph space in PD:

For configuration-only changes, keep the installed Chart version and values. Find the version with helm list and replace the placeholder below:

1helm list -n hugegraph
2CHART=oci://ghcr.io/hugegraph/hugegraph-helm
3CHART_VERSION='<installed-chart-version>'
4helm upgrade hugegraph "$CHART" --version "$CHART_VERSION" -n hugegraph --reuse-values \
5  --set-string server.serviceId=analytics \
6  --set-string server.graphSpace=team_a \
7  --set-string server.testGraphAlias=team_a-demo

A non-default graph space must be created through the PD API before starting its assigned Server. server.testGraphAlias specifies the Gremlin binding checked by helm test (case-sensitive) and does not auto-infer from graphSpace. Do not re-declare service ID or graph space in server.extraEnv.

3 Internal images and storage

Complete examples cover private registries, dynamic storage, seven local PVs, GitOps credentials, API-only deployment and a hostless HTTP Ingress.

Set global.imageRegistry to prefix unqualified image repositories; an explicit registry in a component repository takes precedence. The default mirror inventory is only hugegraph/pd, hugegraph/store, hugegraph/server and hugegraph/hubble, at the configured tags/digests. Store’s PD wait init container and the Helm test reuse Store and Server images respectively, which already contain curl. No separate curl image or runtime package installation is required. Explicit store.waitImage / server.waitImage overrides remain supported.

Enabled SeaTunnel additionally needs its configured apache/seatunnel image; enabled Vermeer uses the published build pinned above. Vermeer reuses that image for Master, Worker and service-token initialization. Mirror every enabled image and explicit helper override. For a custom Vermeer image, also update vermeer.image.digest, or explicitly clear it when selecting by tag; a nonempty digest takes priority.

Storage configuration

For storage, empty storageClassName inherits the cluster default, while "-" explicitly selects no StorageClass. Local PVs require prepared host directories, matching capacities, nodeAffinity and a kubernetes.io/no-provisioner StorageClass; WaitForFirstConsumer binds with the Pod’s scheduling constraints. See the complete seven-volume example before creating resources. For a new temporary installation, set persistence.enabled=false to use emptyDir; component storage flags override it. The chart never replaces a failed PVC with temporary storage and rejects PD/Store storage-mode changes on initialized releases.

Vermeer uses separate Master and Worker claims, even in its single-Pod mode: two additional volumes in standalone, or one Master volume plus one per Worker in cluster mode. With the default base topology this means 9 or 11 volumes respectively. The small HugeGraph preset plus standalone Vermeer needs 5. The seven-volume local example covers only the base installation. SeaTunnel checkpoints remain temporary local files.

Offline installation and internal repositories

Select the latest version, download that Chart and move the .tgz into your network. Install it directly or upload it to an existing OCI or HTTP repository. In air-gapped environments, override the image registry with --set global.imageRegistry=..., see values-internal-registry.yaml.

1CHART=oci://ghcr.io/hugegraph/hugegraph-helm
2CHART_VERSION=$(helm show chart "$CHART" --devel | sed -n 's/^version: //p')
3helm pull "$CHART" --version "$CHART_VERSION"
Install archive
1# Override the image registry in air-gapped clusters (or use -f values-internal-registry.yaml)
2helm install hugegraph "./hugegraph-helm-${CHART_VERSION}.tgz" -n hugegraph \
3  --set global.imageRegistry=registry.example.com \
4  --create-namespace --wait --timeout 15m
Internal OCI
1helm registry login registry.example.com
2helm push "./hugegraph-helm-${CHART_VERSION}.tgz" oci://registry.example.com/charts
3helm install hugegraph oci://registry.example.com/charts/hugegraph-helm \
4  --version "$CHART_VERSION" -n hugegraph \
5  --set global.imageRegistry=registry.example.com \
6  --create-namespace --wait --timeout 15m
Internal HTTP
1# Upload the same .tgz using your repository's upload mechanism and update index.yaml.
2# For a static HTTP repository, use helm repo index. Native helm push only supports OCI.
3helm repo add hugegraph-internal https://charts.example.com
4helm repo update hugegraph-internal
5helm install hugegraph hugegraph-internal/hugegraph-helm \
6  --version "$CHART_VERSION" -n hugegraph \
7  --set global.imageRegistry=registry.example.com \
8  --create-namespace --wait --timeout 15m

Replace the example registry addresses with your own. The archive contains no container images: mirror all configured container images separately, then override their addresses.

4 Authentication and secrets

Normal Helm installations generate and reuse three credentials: <release>-admin (password), <release>-auth-token (token_secret) and <release>-pd-auth (secret-key). PD REST requires the shared PD secret, supplied to the PD container as HG_PD_AUTH_SECRET_KEY; Server’s storage wait and Hubble read the same credential. It is not a separate user password that must be invented for each Pod.

For GitOps, use fixed encrypted values or pre-created Secrets through pd.auth.existingSecret, server.auth.admin.existingSecret and server.auth.token.existingSecret. existingSecret wins over inline values and is not managed by the chart. The admin password must be printable ASCII without spaces, colons or backslashes; the PD secret must be printable ASCII without surrounding whitespace or backslashes; the JWT signing key must be at least 32 bytes. Offline renderers cannot reuse live generated Secrets through lookup.

The admin Secret is an initial credential. Updating it does not rotate an existing account. Change the password through PUT /graphspaces/DEFAULT/auth/users/admin with {"user_password":"<new-password>"} using the existing credential, update the Secret/source to that same password, then restart the Server Deployment to clear every replica’s auth cache.

Hubble is enabled by default and its current login requires Server authentication. Set hubble.enabled=false for API-only access; optionally also set server.auth.enabled=false for an unauthenticated API. Inactive credential settings may remain in your values file.

Enabled optional engines always require native login, including in easy mode. Newly generated administrator passwords use 6 random alphanumeric characters in easy mode or 16 in strict mode. SeaTunnel uses HTTP Basic, while Vermeer uses Secret <release>-vermeer-admin and its Admin credential login. Upgrades retain existing passwords, including when changing mode; mode changes do not rotate them automatically. Vermeer password sources are vermeer.auth.admin.password or vermeer.auth.admin.existingSecret/key; only Master reads that password. Access native administration according to the final Service type: NodePort connects via the node IP and assigned port, while ClusterIP uses port-forwarding. Hubble service credentials are automatic.

Advanced: Vermeer deployment credentials and GitOps

For GitOps, preserve stable administrator credentials and the separate internal service identity. The service signing factor uses vermeer.auth.value or vermeer.auth.existingSecret/key; Hubble generates its service token automatically. Ordinary Hubble use and native password login do not require retrieving that token. Changing an external native administrator Secret needs a Master restart only. Service-factor rotation requires Master and Hubble, not Workers. Worker Schema reads reuse the deployment administrator unless vermeer.hugegraphCredentials.existingSecret/key supplies protected username/password JSON for an existing account with the required Schema permissions. No account is created automatically.

5 Upgrade and verification

Use native Helm value reuse to preserve an existing deployment’s UI, entry, storage and credentials:

1helm get values hugegraph -n hugegraph --all
2# Follow the latest version for testing; use --version with a reviewed stable version for production.
3helm upgrade hugegraph "$CHART" --devel -n hugegraph \
4  --reuse-values --wait --timeout 15m
5helm test hugegraph -n hugegraph --logs --timeout 5m

Existing explicit helper images also remain under --reuse-values; add --set-string store.waitImage= --set-string server.waitImage= to reuse component images. Adopt new defaults deliberately with --reset-values and a reviewed file retaining your image, credential, storage and topology settings. Do not treat PD membership, storage or credential changes as ordinary independent overrides; consult the lifecycle reference.

PD, Store and Server images built from current master run as UID/GID 10001. The chart gives the PD and Store pods fsGroup: 10001 (with fsGroupChangePolicy: OnRootMismatch) unless their podSecurityContext sets fsGroup, also when --reuse-values keeps an older release’s empty value, so they can write PVCs created by older images, which ran as root.

Switch PD and Store to images built from this version in the same rollout that first applies fsGroup, so the kubelet changes the volume ownership right before the 10001 image starts. Do not run images that still run as root with this chart first, for example a latest that has not moved to this version: files they create stay owned by root, and OnRootMismatch checks only the volume root, so it does not fix them later. Pin pd.image and store.image to a build from this version rather than relying on latest. A non-empty image.digest wins over image.tag, and --reuse-values keeps an existing digest, so a release pinned by digest must change the digest, not only the tag.

If a release already ran root images with fsGroup set, roll out the first 10001 image together with a one-time recursive ownership change. Set the images in the same command, so the recursive change runs for the 10001 image rather than for a pinned root image. The example clears any reused digest so the tag applies; a release pinned by digest sets pd.image.digest and store.image.digest to the digests of this version’s images instead:

1helm upgrade hugegraph "$CHART" --devel -n hugegraph --reuse-values \
2  --set pd.image.tag=<this-version> \
3  --set store.image.tag=<this-version> \
4  --set-string pd.image.digest= \
5  --set-string store.image.digest= \
6  --set pd.podSecurityContext.fsGroupChangePolicy=Always \
7  --set store.podSecurityContext.fsGroupChangePolicy=Always \
8  --wait --timeout 15m

Before switching the policy back, check that every PD and Store Pod runs the 10001 image you set, not an older root image:

1kubectl get pods -n hugegraph \
2  -o jsonpath='{range .items[*]}{.metadata.name}{"\t"}{.spec.containers[*].image}{"\n"}{end}'

--reuse-values keeps Always, which walks the whole volume on every Pod start, so set the policy back once those Pods are running:

1helm upgrade hugegraph "$CHART" --devel -n hugegraph --reuse-values \
2  --set pd.podSecurityContext.fsGroupChangePolicy=OnRootMismatch \
3  --set store.podSecurityContext.fsGroupChangePolicy=OnRootMismatch \
4  --wait --timeout 15m

Volumes whose CSI driver ignores fsGroup (for example many NFS drivers) and hostPath volumes need a one-time chown -R 10001:10001 instead.

server.storageWaitTimeoutSeconds defaults to 300 and is passed as WAIT_STORAGE_TIMEOUT_S. An unspecified startup probe threshold is derived from that wait plus 150 seconds; an explicit threshold is preserved and must cover the storage wait plus at least 120 seconds of Server startup. A contradictory budget fails rendering with the relevant parameter names. Storage wait timeout is not a JVM memory setting.

The default helm test hook checks connectivity and reads. After installation or recovery, also test a new UI login and your application’s read/write queries. For scheduling, NetworkPolicy, rolling updates and recovery, see Kubernetes operations.

6 Deploy and Use SeaTunnel (Optional Engine)

SeaTunnel is an optional data integration engine supported by HugeGraph, disabled by default. When enabled, Helm provisions a persistent SeaTunnel Zeta engine alongside a task Web dashboard within the same release. The official apache/seatunnel:3.0.0 image comes with built-in HugeGraph connectors (Source and Sink), requiring no custom image builds or plugin installation.

 1helm/hugegraph/
 2  examples/
 3    values-seatunnel-standalone.yaml # Standalone preset (1 Hybrid node, lightweight for local/dev use)
 4    values-seatunnel-cluster.yaml    # Cluster preset (multiple Hybrid nodes for distributed parallelism)
 5    seatunnel/
 6      hugegraph-sink.conf            # Import sample: batch inserts test vertices into HugeGraph
 7      hugegraph-source.conf          # Export sample: reads graph data from HugeGraph to stdout/logs
 8      clone/                         # Full graph migration configs
 9        copy-schema.py               # Automated Schema synchronization script
10        person.conf / knows.conf     # Per-label vertex and edge migration job definitions
flowchart TB
    A["External Data Source / Remote Graph"] --> ST
    subgraph Release["Same Helm Release"]
        ST["SeaTunnel Zeta<br/>Hybrid Node"] -->|Read / Write| HG["HugeGraph<br/>Server + PD + Store"]
    end
    U["Operators"] -->|Web UI / REST (HTTP Basic)| ST

6.1 Choose Standalone or Cluster Mode

SeaTunnel uses a Hybrid node architecture where each node handles both job scheduling and execution:

  • Standalone Mode: Starts 1 persistent node, minimizing memory footprint for development and lightweight jobs.
  • Cluster Mode: Starts multiple uniform nodes forming a cluster for distributed high availability and higher throughput.

SeaTunnel scaling is fully decoupled from the HugeGraph cluster topology. Install from the extracted chart directory or repository root by combining presets:

SeaTunnel Standalone
1helm install hugegraph ./hugegraph-helm -n hugegraph --create-namespace \
2  -f ./hugegraph-helm/values-single.yaml \
3  -f ./hugegraph-helm/examples/values-seatunnel-standalone.yaml \
4  --wait --timeout 30m
SeaTunnel Cluster
1helm install hugegraph ./hugegraph-helm -n hugegraph --create-namespace \
2  -f ./hugegraph-helm/values-single.yaml \
3  -f ./hugegraph-helm/examples/values-seatunnel-cluster.yaml \
4  --wait --timeout 30m
Tip

To add SeaTunnel to an existing HugeGraph deployment, simply set seatunnel.enabled: true with the chosen topology values and run helm upgrade. Existing graph services remain uninterrupted. Because the SeaTunnel image is large, mirror it to your private registry beforehand in air-gapped environments.

6.2 Access Web UI and Authentication

SeaTunnel inherits the global mode setting when seatunnel.service.type: null: easy defaults to NodePort, strict to ClusterIP. An explicit ClusterIP stays private; explicit NodePort, including in strict mode, exposes HTTP/UI with the same required login. Clear an older explicit ClusterIP override to null to inherit easy mode. Omit seatunnel.service.nodePort or use null for automatic allocation. The standalone / cluster topology does not change this access choice:

NodePort (easy mode)
1kubectl -n hugegraph get svc hugegraph-seatunnel \
2  -o jsonpath='{.spec.ports[?(@.name=="http")].nodePort}{"\n"}'
3kubectl get nodes -o wide
4# Open browser: http://<NodeIP>:<NodePort>/#/overview
Port-forward (General)
1kubectl -n hugegraph port-forward svc/hugegraph-seatunnel 8081:8080
2# Open locally: http://127.0.0.1:8081/#/overview

The Web dashboard and REST APIs require independent HTTP Basic authentication in both modes, distinct from HugeGraph Server credentials. The username is admin; newly generated passwords use 6 random alphanumeric characters in easy mode or 16 in strict mode. Upgrades and mode changes retain the existing password. Read it from the release Secret:

1kubectl -n hugegraph get secret hugegraph-seatunnel-auth \
2  -o jsonpath='{.data.password}' | base64 --decode
Warning

Port 5801 is reserved for internal Zeta communication and CLI commands; it does not use HTTP Basic auth and remains private. External access uses only the authenticated HTTP Service through its assigned NodePort; the application still listens on 8080.

6.3 Run Pre-configured Example Jobs

The Chart mounts sample jobs inside the SeaTunnel Pod, pre-configured with environment variables referencing the in-release Server address, graph name, and credentials:

  1. Prepare Graph: Ensure an empty target graph exists via Hubble or REST API (default DEFAULT/graph_a).

  2. Run Import Job: Ingest 10 sample vertices under the seatunnel_demo_person label:

    1kubectl -n hugegraph exec sts/hugegraph-seatunnel -- \
    2  /opt/seatunnel/bin/seatunnel.sh --master cluster \
    3  --config /opt/seatunnel/config/hugegraph-sink.conf
  3. Verify with Export Job: Run the Source sample job to read back the same vertices and print them to standard logs:

    1kubectl -n hugegraph exec sts/hugegraph-seatunnel -- \
    2  /opt/seatunnel/bin/seatunnel.sh --master cluster \
    3  --config /opt/seatunnel/config/hugegraph-source.conf

Inspect job status and DAG progress in real time on the Web dashboard. To use custom graphs or credentials, override environment variables under seatunnel.env or mount external configurations via seatunnel.config.

6.4 Full Migration and Topology Switches

  • Topology Switch: Switch between standalone and cluster modes by updating values and running helm upgrade. Since the engine process restarts, complete all running batch jobs before switching.
  • Full Graph Migration: Follow the sequence Schema metadata → Vertices → Edges. See examples/seatunnel/clone/ for automated migration scripts and configs. When migrating fields with DATE types, explicitly specify matching server timezones (e.g. timeZone = "UTC") in the Sink config to prevent timezone shift. See the SeaTunnel Source migration guide for details.

5 - Operate HugeGraph on Kubernetes

This guide accompanies Helm deployment. Detailed lifecycle checks and recovery notes are maintained in the operations reference; all parameters are commented in values.yaml. Commands assume release/namespace hugegraph; substitute the actual workload names if overridden.

1 Storage and private images

The base installation needs seven persistent volumes. Dynamic storage requires a working provisioner; static local storage requires prepared directories and matching PVs on the named nodes. Use the complete examples for all seven local PVs, WaitForFirstConsumer, registry mirrors and GitOps Secrets. An initially Pending PVC with WaitForFirstConsumer can be normal; persistent Pending needs PVC/Pod events and PV matching checks. A bound claim with a missing directory or permission mismatch can fail mounting. Do not replace failed PVCs with temporary data directories.

1kubectl -n hugegraph get pvc,pods
2kubectl -n hugegraph describe pvc <claim-name>
3kubectl -n hugegraph describe pod <pod-name>
4kubectl get pv,storageclass

For ImagePullBackOff, inspect Pod events and registry access/credentials. The default image inventory contains four component images; Store wait and Helm test reuse existing component images with curl already installed. Explicit helper-image overrides must also be mirrored. Enabled SeaTunnel adds its configured apache/seatunnel image. Enabled Vermeer uses hugegraph/vermeer:helm-30b67d93e7d0, pinned by digest and reused by Master, Worker and token initialization. Official publishing runs record the source and image digest; see the Vermeer deployment guide. Custom image overrides must also update vermeer.image.digest, or explicitly clear it to select by tag; digest takes priority. The base local-PV example omits Vermeer claims: standalone adds two, while cluster adds one Master claim plus one per Worker (four additional claims by default).

2 Ports and health

PD listens on REST 8620, gRPC 8686 and Raft 8610; Store on REST 8520, gRPC 8500 and Raft 8510; Server HTTP on 8080; Hubble HTTP on 8088. Client Services hide individual Pod addresses. NodePort is a separate allocated port on reachable nodes, not the application listener port. PD /v1/ready requires a Raft leader; /v1/health only confirms the listener. Store startup waits for a majority of ready PD peers. Server waits up to server.storageWaitTimeoutSeconds (default 300) before its application startup; adjust it for slow storage bootstrap. No local Helm rendering verifies live cluster reachability, volumes or JVM capacity.

Preserve the metadata namespace

metadataCluster: hg-test sets the PD metadata namespace prefix (injected into Server HG_SERVER_CLUSTER and Store PD_CLUSTER). It is not a Raft group name; changing it will not automatically migrate existing metadata. Never arbitrarily change this prefix on an initialized cluster to enable Vermeer. If Server REST queries succeed but Vermeer scanning Store fails with Schema missing or no such vertex label, check that the namespace prefix matches across all components.

If a legacy environment used a custom prefix, record it explicitly on the Server Deployment before upgrading:

1kubectl -n hugegraph annotate deployment hugegraph-server \
2  hugegraph.apache.org/metadata-cluster='<verified-existing-namespace>'

and ensure metadataCluster matches this value in your values file. For Store nodes using store.updateStrategy.type=OnDelete, follow the rolling upgrade procedure to recreate Pods one by one so the new settings take effect.

Optional Engines Operations: Probes, Credentials, and Topology Switching
  • Ports & Health: SeaTunnel HTTP/UI runs on 8080; Vermeer Master HTTP/gRPC listens on 6688/6689, and Worker on 6788/6789. Native HTTP/UI defaults to NodePort in easy mode and ClusterIP in strict mode; both require login. Internal RPC, Worker HTTP and SeaTunnel 5801 stay private. With service.type: null, the mode default applies; explicit ClusterIP stays private, while explicit NodePort exposes authenticated HTTP/UI. Use the assigned HTTP NodePort from Service hugegraph-seatunnel or hugegraph-vermeer-master with a reachable node IP. See native access commands; ClusterIP access can use port-forwarding.
  • Credentials & Sessions: Generated admin passwords use 6 characters in easy mode or 16 in strict mode, retained across upgrades and mode changes. In Vermeer native UI, enter the password from Secret <release>-vermeer-admin into Admin credential; Hubble internal service tokens are auto-wired.
  • Topology Changes: Ensure active computations and batch ingestion jobs are complete and in-memory graphs are unloaded before changing seatunnel.mode or vermeer.mode. Standalone and cluster use separate PVC claims, so mode changes do not migrate local files.
  • See the Vermeer Guide and SeaTunnel Guide for full recovery and configuration details.

Helm test coverage

helm test validates graph binding on every Server Pod (DEFAULT-hugegraph by default, or configured via server.testGraphAlias), and requires currently visible associated indexes to be in CREATED state. Run it after index creation/rebuild jobs finish, with no schema changes during the test. On HStore, reading an unfinished index can cache its temporary status on other Pods; retries do not refresh that state. Indexed queries on those Pods may keep failing after the job succeeds; replace affected Server Pods only after the jobs finish. The hook does not fix cross-Server schema cache consistency. Its 150-second internal retry window allows transient elections to settle; Helm’s --timeout does not change that window. It reads indexes by ID without refreshing the full index cache; it does not prove index query results or complete schema consistency. For existing data, use --set-file server.testGremlin=assertions.groovy during Helm upgrade to add read-only business assertions on every Pod. The script must use assert or throw on unexpected results; returning false alone does not fail the request. See business query assertions for an example and coverage limits. Without a script, business assertions are reported as skipped. The default hook creates no schema or data. Custom scripts use the hook’s Server credential (admin with auth enabled); read-only execution is not enforced, so supply trusted, read-only assertions.

Server API responses negotiate compression through Accept-Encoding. Gzip-capable clients can request gzip or use curl --compressed; identity or no compression request keeps the response uncompressed. Build a new Server image from the updated source to include this behavior; updating the chart alone does not update an existing image.

PD REST authentication

PD REST uses HTTP Basic auth: hg, store, hubble and vermeer share the PD REST Secret password. Server’s admin account is not a PD REST account and receives 401. For the default release/Secret and a reachable PD REST address:

1PD_SECRET=$(kubectl -n hugegraph get secret hugegraph-pd-auth \
2  -o jsonpath='{.data.secret-key}' | base64 --decode)
3curl --user "hg:${PD_SECRET}" "http://<pd-rest-address>:8620/v1/stores"

The HTTP example assumes a trusted internal network. For other access paths, use an HTTPS gateway or optionally forward the PD Service: kubectl -n hugegraph port-forward service/hugegraph-pd-client 8620:8620, then query http://127.0.0.1:8620.

With pd.auth.existingSecret or a custom pd.auth.key, read the actual Secret and key. Do not use the Server admin password. Variables avoid literal passwords in shell history, but expanded credentials can briefly appear in process arguments. On shared terminals, use curl --user hg to prompt for the password or a private curl config with permissions 600; the credentials guide also covers password-update payloads. Keep credential files out of logs and version control.

3 Scheduling

The default preferred anti-affinity permits scheduling with fewer nodes than replicas. values-cluster.yaml sets required PD/Store anti-affinity, so it needs at least three schedulable nodes. Explicit affinity takes priority over presets. Local PV node affinity must match the workload’s placement constraints; PV capacity declarations do not enforce filesystem quotas. Do not change a persisted PD/Store Raft hostname or port as an ordinary upgrade: those addresses are recorded identities.

4 Partition sharding

At first bootstrap, the chart seeds three shard replicas when there are at least three Stores, and one otherwise. PD persists the partition settings; changing chart values after initialization does not rewrite that metadata. Use the PD configuration API and a coordinated partition patrol for an existing cluster. An explicit shard count must be odd and no greater than Store replicas. See the topology constraints before changing a live cluster; the chart does not migrate existing shard metadata.

5 NetworkPolicy

Easy mode and the ordinary cluster preset leave full base-service isolation disabled by default; strict enables it. SeaTunnel and Vermeer always require login. Their native policies allow external HTTP only when the final Service type is NodePort, while internal RPC, Worker HTTP and SeaTunnel member ports retain their release-caller restrictions, even with networkPolicy.enabled=false. The cluster network plugin must enforce NetworkPolicy for these resources to have an effect. The generated policies admit component traffic and DNS. For base services, external clients and Ingress controllers need suitable networkPolicy.<component>.extraIngress rules; external discovery addresses may need matching extraEgress. For base-service rules, an empty list can block outside traffic and native Kubernetes rules include {} to allow all; there is no separate source-acknowledgement gate. Use your actual source addresses/selectors, considering NodePort SNAT and controller behavior.

 1networkPolicy:
 2  enabled: true
 3  server:
 4    extraIngress:
 5      - from:
 6          - ipBlock:
 7              cidr: 10.20.0.0/16
 8        ports:
 9          - protocol: TCP
10            port: 8080
11  hubble:
12    extraIngress:
13      - from:
14          - ipBlock:
15              cidr: 10.20.0.0/16
16        ports:
17          - protocol: TCP
18            port: 8088

Native-engine extraIngress accepts explicit internal Pod/namespace selectors only; IP blocks and unrestricted rules are rejected. NodePort HTTP access is admitted by the generated policy without an extraIngress rule. The base-service example above applies to Server. External data destinations can use engine extraEgress; strict mode additionally enforces egress isolation.

6 Rolling Store images safely

Use store.updateStrategy.type=OnDelete for a controlled maintenance rollout, as the cluster preset does. Delete one Store Pod at a time. Before replacing the next, verify the previous Pod is Ready, has a fresh Store heartbeat and each shard group has its full membership and exactly one leader, read from the PD leader. PD’s Up status alone does not prove completed shard recovery. PDBs limit voluntary eviction, not StatefulSet controller disruption. Stop on missing members or leaders. The operations reference summarizes these rollout conditions; it does not provide a complete per-group diagnostic or disk-loss recovery procedure.

A single Store replacement can cause request errors or timeouts while Raft leadership and client routes converge, even with full replicas. There is no zero-error guarantee. Observe application errors as well as shard recovery before continuing; do not blindly retry writes.

PD patrol and leader balance

Partition patrol repairs shard membership; leader balance is a separate manual task and is not scheduled automatically. Before either task, identify the PD leader through authenticated /v1/members (data.pdLeader.restUrl) and confirm its /v1/ready reports isLeader: true. The GET tasks /v1/task/patrolPartitions and /v1/task/balanceLeaders change cluster state; target that confirmed leader with PD REST credentials. Wait for membership recovery and split/move tasks to finish before balancing leaders; Stores must have fresh heartbeats and groups full, healthy membership. A busy task returns body status: 1001. A follower may return empty success, and leader transfers are asynchronous: HTTP 200 or a transfer plan does not prove completion. Recheck /v1/partitions, /v1/stores and application errors before further maintenance. Follow the task procedure for the separate patrol and balance steps; do not loop task requests while maintenance is busy.

7 Disaster recovery

Preserve existing volumes, claim identities and PD membership. Do not delete RocksDB lock files to recover a deployment, or replace persisted membership with freshly generated nodes. A new empty PVC does not restore the data from a lost Store disk. Local disks cannot migrate their files automatically when a node fails. Take backups outside these PVs and test recovery separately. The chart does not implement backup or automatic recovery. The recovery notes describe constraints, not a complete recovery sequence. Before destructive changes, establish and validate a recovery plan for the deployed version and remaining replicas or backups.

8 Scaling

Server replicas are routinely mutable; an HPA also needs CPU requests. Store growth is a coordinated storage/shard operation. PD growth/shrink and Store shrink cannot be handled as ordinary replica changes, because persistent Raft/shard membership must be updated first. Chart upgrade checks reject unsupported identity/membership changes on initialized StatefulSets; fresh installs do not query StatefulSets for upgrade checks. Scale through the documented lifecycle procedure rather than kubectl scale, which can leave Hubble’s Store metrics configuration stale.

9 Running Hubble outside the cluster

Direct mode only needs an externally reachable Server URL. PD discovery also needs externally reachable PD gRPC, and Server addresses registered with PD must be reachable from that external Hubble. Set server.advertiseUrl to a shared reachable Server URL when needed; it affects all discovery clients, including in-cluster Hubble. In-chart Hubble already uses internal service discovery and needs no public PD entry point. HTTP is supported directly; TLS termination remains optional. Hubble remains single-replica and its current login requires Server authentication.

10 When Gremlin fails with Could not rebind

A Server can become Ready and serve REST while Gremlin binding failed during a PD rollout. Run helm test hugegraph -n hugegraph --logs --timeout 5m; the hook checks authenticated graph-bound Gremlin on every Server Pod. Once PD is stable, replace the failing Server Pod and verify again. A test that only calls /versions does not prove graph binding; also check fresh Hubble login and a graph query.

For ERROR: missing required env 'HG_PD_AUTH_SECRET_KEY', inspect the PD Pod’s Secret reference and the corresponding key, not the Secret value in logs. The chart normally injects this shared PD REST credential automatically. Custom containers/manifests must provide the same value to PD and its clients. In GitOps, create the external Secret before workload reconciliation; with ordinary Helm, retain the chart-generated release Secret.