Upgrade ArcadeDB

ArcadeDB automatically upgrades a database to a newer on-disk format when a newer version of ArcadeDB opens it. The migration is transparent and happens lazily on first open, so the only operator step is to point the new binaries at your existing data.

Breaking changes

This section lists behavior changes that may require action when upgrading.

26.7.2 — Durable Raft storage is now the default

arcadedb.ha.raftPersistStorage now defaults to true (previously false). The per-node Raft log under raft-storage-<nodeName> is persisted across restarts so a node can rejoin by replaying its own log instead of always requiring a full snapshot resync. Wiping the log on restart could previously diverge a lagging follower after a full-cluster cold restart (WALVersionGapException) or silently re-form a fresh single-node cluster.

Impact: HA clusters only.

Action: ensure arcadedb.ha.raftStorageDirectory (or the default raft-storage- location under the server root) lives on *durable storage — a persistent volume, not an ephemeral or tmpfs mount. On Kubernetes, back it with a PersistentVolumeClaim. A throwaway/test cluster can opt out with arcadedb.ha.raftPersistStorage=false. See Durable Raft Storage.

26.7.2 — Bolt temporal values are now native PackStream types

Over the Neo4j Bolt protocol, date, time, localtime, datetime and localdatetime are now carried as native PackStream temporal structures in both directions, matching Neo4j. Previously they were serialized as ISO-8601 strings (and inbound datetime query parameters were silently dropped).

Impact: Bolt/Neo4j-driver clients that read a temporal property as a String.

Action: read temporal properties with the driver’s native temporal accessors (e.g. Value.asZonedDateTime(), asLocalDate()), exactly as you would against Neo4j. See Bolt data type mapping.

26.7.1 — Cypher IS TYPED INT is now 32-bit (INTEGER)

A Cypher constraint REQUIRE p.x IS TYPED INT now declares a 32-bit INTEGER property, where it previously declared a 64-bit LONG. This aligns the write side with the value-type predicate (x IS TYPED INT), which already evaluated INT as the 32-bit INT32 alias per ISO/IEC 39075 (GQL) / Cypher 25 — so a value larger than Integer.MAX_VALUE stored in such a column already failed its own IS TYPED INT predicate.

Impact: only schemas that used the bare INT keyword (not INTEGER) in a Cypher IS TYPED constraint. A property declared IS TYPED INT can no longer hold values outside the 32-bit signed range.

Action: change IS TYPED INT to IS TYPED INTEGER (or IS TYPED INT64) where 64-bit width is required. See IS TYPED data types for the full GQL numeric type mapping.

Single-server upgrade

  1. Download and extract the new ArcadeDB release in a separate directory (do not overwrite the old install).

  2. Stop the running server (or close every open database via the HTTP close database command).

  3. Copy the directories listed in What to copy from the old install into the new install, preserving the original paths.

  4. Start the new server.

When the server starts, every database is opened with the new code and any required format migration is applied in place.

What to copy

ArcadeDB’s root directory contains a fixed set of folders. Only a few of them hold user-owned state; the rest are recreated from the release archive on every install.

Folder Action Notes

databases/

Copy

The actual database data. Every subdirectory is one database. This is the only folder strictly required for an upgrade.

config/

Copy selected files

The release ships a default config/ directory. Carry over only the files you have actually modified — listing below.

backups/

Copy if you want history

Backup archives produced by manual or automatic backups. The server does not need them to start; copy them only if you want to keep the backup history reachable from the Studio Backup tab and from RESTORE DATABASE commands.

log/

Skip

Server log files. Safe to start with an empty log/ directory; the release ships an empty one. Copy only if you want to keep historical logs alongside the new install.

raft-storage-<peerId>/ (HA only)

Copy (since v26.7.2)

Per-node Raft log segments, created at runtime when HA is enabled. Since v26.7.2 this storage is durable by default (arcadedb.ha.raftPersistStorage=true) and must be preserved so a node can rejoin by replaying its log instead of a full snapshot resync. On releases before v26.7.2, or when raftPersistStorage is explicitly false, it is ephemeral and can be skipped. See HA cluster upgrade for details.

replication/

Skip

Legacy directory from the pre-Raft replication implementation. Not used by the current HA stack.

lib/, bin/

Use the new release as-is

Java artifacts and start scripts. Always take them from the new release — do not copy from the old install. The only exception is custom JARs you have dropped into lib/ yourself; carry those over by hand.

Files to carry over from config/

The config/ directory ships with a small set of defaults. You only need to copy the files that you have actually changed:

File When to copy

server-users.jsonl

Always, unless you create users only via REST/SQL on every upgrade. This is where ArcadeDB persists local users and their per-database group assignments.

server-groups.json

If you have customised the security policy (custom groups, type-level permissions, result-set limits). See Security Policy.

backup.json

If you have configured the auto-backup scheduler (schedule, retention, target directory). See Automatic Backup.

arcadedb-log.properties

If you have tuned java.util.logging settings (log levels, rolling file size, etc.).

gremlin-server.yaml, gremlin-server.groovy, gremlin-server.properties

Only if you use the embedded Gremlin Server and have edited any of these.

Everything else under config/ (arcadedb-log-all.properties, arcadedb-statefulset.yaml, …) ships unchanged with each release; take the new version.

ArcadeDB does not read a config/server-configuration.json file in normal operation. Server-wide settings come from JVM system properties, environment variables and the arcadedb-server.sh arguments — see Server Configuration.

HA cluster upgrade

An HA cluster (see High Availability) is upgraded one node at a time. The per-node procedure is the same as single-server above, with the following clarifications.

What to migrate on each node:

  • databases/ — copy, exactly as in the single-server case.

  • config/ — copy the same files as in the single-server case. The cluster’s identity is derived from arcadedb.ha.clusterName and the root password (the inter-node token is computed from them at startup), so as long as every node keeps the same cluster name and the same root password, the upgraded cluster reattaches to itself without any extra step.

  • raft-storage-<peerId>/copy (since v26.7.2). Since v26.7.2 the local Raft log is durable by default (arcadedb.ha.raftPersistStorage=true), so preserve this directory across the upgrade to let the node rejoin by replaying its own log. Whether or not it is preserved, after the upgraded node rejoins the cluster the leader replays any missing entries via Raft or, if the node has fallen behind the purge boundary, streams a full snapshot over HTTP automatically. On releases before v26.7.2 (or with raftPersistStorage=false) this directory is ephemeral and can be skipped.

  • backups/ and log/ — same as single-server.

Recommended rolling upgrade flow (zero downtime, requires quorum at all times):

  1. Pick a non-leader node first.

  2. Stop the node, install the new release in a separate directory, copy the folders listed above, start the new binary.

  3. Wait until GET /api/v1/cluster reports the node as healthy and caught up (replication lag near zero).

    1. The Studio Cluster tab shows the same information visually.

  4. Repeat for every remaining replica.

  5. Step the leader down with POST /api/v1/cluster/stepdown (or simply stop it — Raft will elect a new leader) and upgrade it last.

For first-time HA bring-up with a pre-existing database (e.g. when you scale a single-node install into a cluster), see Offline Cluster Bootstrap.

Docker / Kubernetes

When you run ArcadeDB from the official container image, the release is replaced atomically by changing the image tag. The only data that survives across container restarts is what lives on a persistent volume, so:

  • Mount /home/arcadedb/databases on a persistent volume — this is the equivalent of "copy the databases/ folder".

  • Mount /home/arcadedb/config only if you have edited the files listed in Files to carry over from config/; otherwise let the image ship its defaults.

  • Set arcadedb.ha.raftStorageDirectory to a static path (e.g. /home/arcadedb/raft-storage) and mount that path on a persistent volume. The default per-node directory is named raft-storage-<nodeName> dynamically, which a container runtime or Kubernetes cannot mount as a volume (a wildcard like /home/arcadedb/raft-storage-* is created literally, not expanded) — this is exactly what raftStorageDirectory is for. Since v26.7.2 the Raft log is durable by default (arcadedb.ha.raftPersistStorage=true) so a restarted pod can replay its own log instead of resyncing from peers. On releases before v26.7.2, or with raftPersistStorage=false, the log is ephemeral and this mount is unnecessary.

  • Mount /home/arcadedb/backups if you want to retain backup archives across pod restarts.

For Kubernetes specifics (StatefulSet, headless service, init container for pre-staging a database), see Kubernetes.

Downgrade ArcadeDB

In case you need to downgrade to an older version of ArcadeDB, check the binary compatibility between the versions. ArcadeDB uses semantic versioning with 100% on-disk compatibility for migration of databases up or down between patch versions (the Z in X.Y.Z). For minor or major downgrades the safest path is to export the database with the newer version and re-import it with the older version.