Native Image (Experimental)
ArcadeDB is also distributed as a native executable of the server, compiled ahead of time with GraalVM Native Image. The native server needs no Java runtime, starts in a fraction of a second and uses far less memory than the same server on a JVM, which suits containers, serverless-style deployments and quick local testing.
| The native image is an experimental add-on. It does not replace the standard JVM distribution described in how-to/operations/binaries.adoc#binaries and how-to/operations/install-docker.adoc#install-docker, which remains the default, fully supported way to run ArcadeDB and the one the rest of this manual assumes. Use the native image when fast startup and a small memory footprint matter more than having every module available, and treat it as best-effort outside Linux. |
Getting the Native Image
Docker images. The native server is published on Docker Hub in the same arcadedata/arcadedb repository as the JVM image, under its own tags:
| Tag | Content |
|---|---|
|
A release, as a multi-architecture image for |
|
The same release for one architecture only. |
|
The nightly build of the |
|
The same nightly build, tagged with the version under development. |
The nightly tags also exist per architecture (latest-native-amd64, latest-native-arm64 and so on).
The two architectures use different base images: the linux/amd64 binary is fully static (musl libc) and runs on an empty scratch image, while the linux/arm64 binary links glibc dynamically and runs on gcr.io/distroless/base-debian12.
Release archives. Each GitHub release carries the native executable for several platforms, each with a .sha256 checksum file:
| Platform | Asset | Status |
|---|---|---|
Linux x86-64 |
|
Required for every release. Fully static, runs on any Linux. |
Linux ARM64 |
|
Required for every release. Needs glibc on the host. |
Windows x86-64 |
|
Best-effort: missing from a release whose Windows build failed. |
macOS ARM64 (Apple Silicon) |
|
Best-effort: missing from a release whose macOS build failed. |
The archive contains a single executable with the same name as the archive, minus the extension (.exe on Windows).
Studio and the configuration templates are embedded in it.
CPU Requirements
A native binary is compiled for one CPU baseline and starts only on a CPU that has every feature of it.
native/pom.xml states the baseline explicitly through the native.march property, which a profile sets per build architecture, instead of inheriting the builder’s default.
The published images and release archives use these baselines:
| Architecture | Baseline | Required CPU features | Excludes, for example |
|---|---|---|---|
amd64 (Linux, Windows) |
|
AVX, AVX2, BMI1, BMI2, FMA, F16C, LZCNT, MOVBE |
Intel before Haswell (2013), AMD before Excavator, Atom, Celeron and Pentium parts without AVX, and VMs whose CPU model hides AVX2 (the QEMU default |
arm64 (Linux, macOS Apple Silicon) |
|
ASIMD (the ARMv8.0 baseline) |
None: runs on every 64-bit ARM core, including the Cortex-A53 and A72 (Raspberry Pi 3 and 4) and Graviton1 |
x86-64-v3 is also GraalVM 25’s own default on amd64.
On arm64 the builder’s own default is armv8.1-a (CRC32 and LSE atomics), and armv8-a is a deliberate choice below it, so that ARMv8.0 cores keep working.
(Since v26.11.1: the arm64 baseline was briefly recorded as armv8.1-a, which excluded those cores, and is armv8-a again.)
On an older CPU the binary exits as soon as it starts, with:
The current machine does not support all of the following CPU features that are required by the image: [...]. Please rebuild the executable with an appropriate setting of the -march option.
To check a Linux amd64 host, run /lib64/ld-linux-x86-64.so.2 --help: on glibc 2.33 and later it lists x86-64-v3 (supported, searched) when the CPU qualifies.
Otherwise look for the avx2, bmi2 and fma flags in /proc/cpuinfo.
In a VM, expose the host CPU (-cpu host in QEMU, CPU type host in Proxmox) or a model that supports x86-64-v3.
If the CPU does not qualify, either:
-
download the
linux/amd64compatibility archive of the release,arcadedb-<version>-linux-x86_64-compat.tar.gz, built with-march=compatibility(the default archive isarcadedb-<version>-linux-x86_64.tar.gz). It starts on any x86-64 CPU, including pre-Haswell hardware, QEMU’sqemu64and Proxmox’sx86-64-v2-AES. It is an archive only: there is no Docker image for it, and the published images keep the baselines in the table above. To run it in a container, build the image yourself with./native/scripts/build-native-docker.sh --march compatibility, -
run the JVM image (
arcadedata/arcadedb:<version>) or the JVM distribution, whose JIT compiles for the CPU it runs on, or -
build a native binary for a lower baseline with
-Dnative.march=compatibility, which runs on any x86-64 or ARMv8 CPU (see Building the Native Image Yourself).
Running the Native Server
Run the executable directly, passing settings as -D arguments exactly as you would pass them to the JVM:
tar -xzf arcadedb-26.10.2-linux-x86_64.tar.gz
./arcadedb-26.10.2-linux-x86_64 -Darcadedb.server.rootPassword=<your-password>
The server uses the current directory as its root path, so it creates databases/ and its other directories there unless you set arcadedb.server.rootPath.
Studio is then available at http://localhost:2480.
To run the Docker image:
mkdir -p databases && sudo chown 1000:1000 databases # only for a bind mount, see below
docker run --rm -p 2480:2480 -p 5432:5432 \
-v "$(pwd)/databases:/home/arcadedb/databases" \
arcadedata/arcadedb:26.10.2-native \
-Darcadedb.server.rootPassword=<your-password>
The native images differ from the JVM image in a few ways, because neither base image contains a shell:
-
Settings are trailing arguments, not environment variables. The JVM image’s
bin/server.shexpandsARCADEDB_SETTINGSandJAVA_OPTSonto the command line. The native image starts the binary directly, so pass-Darcadedb.server.rootPassword=…and any other setting as arguments after the image name, as in the example above. -
User. (Since v26.11.1) Both native images run as UID/GID
1000:1000, the same user as the JVM image, so no--useris needed and a volume written by any of the three images can be mounted by the others. Anonymous and named volumes start owned by1000:1000and are writable out of the box. A bind mount keeps the ownership of the host directory, so every bind-mounted path the server writes (databases, but alsoconfigandlog) must be writable by UID 1000, otherwise the server fails to start with anAccessDeniedException. To run as another UID, pass--user <uid>:<gid>and give that UID ownership of every volume and bind mount, includingconfigandlog. -
Upgrading from an earlier native image. Before v26.11.1 the
linux/amd64image ran as root and thelinux/arm64image as the distrolessnonrootuser (65532), so the volumes they wrote are owned by those UIDs. Re-own each one once before starting the new image:docker run --rm --user 0 -v <volume>:/data busybox chown -R 1000:1000 /dataThe same command makes those volumes usable by the JVM image.
-
Ports. The image exposes
2480(HTTP API and Studio),2434(Raft replication),5432(PostgreSQL),6379(Redis),27017(MongoDB),7687(Bolt) and50051(gRPC). There is no port8182, because Gremlin is not included. Publish the ports of the protocol plugins you enable inarcadedb.server.plugins. -
Volumes.
config,databases,backups,replicationandlogunder/home/arcadedb, as in the JVM image.
What the Native Image Includes
-
The SQL and OpenCypher query engines
-
The HTTP API and Studio
-
The PostgreSQL, Redis, MongoDB, Neo4j Bolt and gRPC wire protocols
-
JavaScript scripting through GraalJS (see the security caveat below)
-
The
consoleandgraphqlmodules -
(Since v26.10.2) Raft high availability, enabled the same way as on the JVM (
-Darcadedb.ha.enabled=trueand-Darcadedb.ha.serverList=…): see how-to/operations/ha.adoc#howto-high-availability -
(Since v26.10.2) Metrics: the Prometheus endpoint (
/prometheus, enabled by addingcom.arcadedb.metrics.prometheus.PrometheusMetricsPlugintoarcadedb.server.plugins) and OTLP metrics push (-Darcadedb.serverMetrics.otlp.enabled=true) -
(Since v26.10.2) Tracing: OpenTelemetry spans over OTLP (
-Darcadedb.serverMetrics.tracing.enabled=true)
A plugin named in arcadedb.server.plugins that is not in the image is skipped without a log line.
If a setting appears to do nothing, check that its module is part of the native image before looking for a configuration mistake.
Limitations Compared to the JVM Distribution
-
No Gremlin. Apache TinkerPop is not part of the native build. If you need Gremlin, use the JVM distribution.
-
No SIMD vector math. (Since v26.10.2) A native image does not compile the Java Vector API into SIMD instructions, so ArcadeDB switches vector index builds, vector functions, Graph OLAP and time series to their scalar implementations when it detects a native image. Results are identical, but vector-heavy workloads run slower than on the JVM, where the Vector API is compiled to SIMD. To force a different JVector provider anyway, set the
jvector.vectorization_providersystem property. -
Thai full-text analyzer.
org.apache.lucene.analysis.th.ThaiAnalyzerfails with "This JRE does not have support for Thai segmentation", because the JDK’s Thai dictionary is not available in the image. The other analyzers work. -
JavaScript is not hardened for untrusted callers. Embedding GraalJS required relaxing a Truffle safety check for a few standard builtins (
Atomics.*,SharedArrayBuffer,TypedArray.prototype.set), and any authenticated user who can runjscommands can reach them. Do not expose the native image’s JavaScript surface to untrusted users in a shared or multi-tenant deployment. -
Certificate trust store. The image carries a snapshot of the build machine’s JDK
cacertstrust store, taken at build time. The CA bundle copied into the Docker images serves only code paths that read the operating system’s bundle explicitly; it does not change the trust anchors baked into the binary. -
Size. The executable is large, around 907 MiB on macOS ARM64, because every classpath resource, including the Studio assets, is embedded in it.
Building the Native Image Yourself
Most users should download a published binary or image.
Two scripts in the ArcadeDB source tree build one.
build-native.sh needs GraalVM Community Edition 25.0.2 installed (the exact version the build pins), with both JAVA_HOME and GRAALVM_HOME pointing at the GraalVM home.
build-native-docker.sh needs only Docker: it fetches the pinned GraalVM into a throwaway builder image.
./native/scripts/build-native.sh # binary for the current platform
./native/scripts/build-native-docker.sh # Linux Docker image for the current architecture
By default the build targets the baseline of the published binaries (see CPU Requirements).
To build for an older CPU, lower it: compatibility runs on any x86-64 or ARMv8 CPU, and x86-64-v2 (amd64 only) needs SSE4.2 and POPCNT but no AVX.
A lower baseline gives up the AVX2, FMA and BMI2 (or LSE) code of the default build.
./native/scripts/build-native.sh -- -Dnative.march=compatibility
./native/scripts/build-native-docker.sh --march compatibility
mvn -Pnative -pl native -am -DskipTests -Dnative.march=compatibility package
Do not distribute a binary built with -march=native: it requires every feature of the CPU that built it.
Native Image cannot cross-compile: each build produces a binary for the platform it runs on, and build-native-docker.sh builds the Linux binary inside a container so it also works on macOS.
The build is memory hungry. build-native-docker.sh requires a Docker VM with about 16 GiB of memory, and for a local build-native.sh you can set the builder heap with NATIVE_IMAGE_OPTIONS="-J-Xmx24g" if the default runs out of memory.
See docs/native-image.md in the ArcadeDB repository for the full build reference.