Storage SPARQL HTTP
The DKG node can use any SPARQL 1.1 Protocol–compliant store you run yourself, instead of its default daemon-managed local Oxigraph server (or the embedded oxigraph-worker fallback). That gives you:
Real on-disk persistence (e.g. Oxigraph server with RocksDB)
Larger graphs without holding everything in the Node process
Existing infrastructure (GraphDB, Blazegraph, Jena Fuseki, Neptune, Stardog)
Backend: sparql-http
Configure the node to use the sparql-http backend with a query endpoint. updateEndpoint is optional and defaults to queryEndpoint, which covers stores that use one URL for both query and update.
Config (CLI / config.json)
In ~/.dkg/config.json (or your DKG_HOME config):
{
"name": "my-node",
"apiPort": 9200,
"listenPort": 9001,
"store": {
"backend": "sparql-http",
"options": {
"queryEndpoint": "http://127.0.0.1:7878/query",
"updateEndpoint": "http://127.0.0.1:7878/update"
}
}
}Optional:
updateEndpoint— SPARQL update endpoint. Defaults toqueryEndpointwhen omitted.timeout— request timeout in ms (default30000).auth—Authorizationheader value, e.g."Bearer <token>"or"Basic <base64>".
Oxigraph server
Install and run Oxigraph (Rust binary with RocksDB):
Download from oxigraph/oxigraph releases or build from source.
Run the server, e.g.:
Default paths are often
/queryand/update(check the server’s docs).
Point the DKG at it using the
sparql-httpconfig above with your host/port.Start the DKG node as usual; it will use the remote store for all triples.
Managed Oxigraph accepts optional launch settings under store.options:
The daemon sizes the startup readiness wait automatically from the RocksDB write-ahead log retained in location. Oxigraph is not closed cleanly on shutdown (it installs no SIGTERM handler), so every start replays the previous session's log, and that replay is what a fixed deadline used to cut short. The derived wait assumes a pessimistic 4 MB/s replay floor and is not truncated below that work allowance; when a replay is pending the daemon logs the size and the allowance, then reports progress every 10 seconds.
readyTimeoutMs overrides that automatic sizing with an explicit maximum, used verbatim and never extended. It must be a positive integer; invalid values are ignored. You normally should not set it — if you configured it as a workaround for a node that would not start, remove it. When an explicit value is lower than the automatic estimate the daemon logs a warning naming both numbers, because that combination is what keeps a recovering node down.
clientTimeoutMs is the SPARQL HTTP client deadline in milliseconds. Managed Oxigraph defaults to 30 seconds. When you configure a longer client deadline, the daemon automatically derives a native query deadline five seconds earlier (for example, 180000 derives 175 seconds). If an Oxigraph evaluator path does not honor native cancellation before the client deadline, the daemon terminates and supervises a fresh managed Oxigraph process so the store cannot remain stalled indefinitely.
queryTimeoutS is the native Oxigraph query timeout in seconds and is passed to oxigraph serve --timeout-s. The default is 25 seconds. An explicit value overrides the derived native deadline; when necessary, the daemon extends clientTimeoutMs so the native timeout still fires at least five seconds before the HTTP deadline. The native deadline applies to query evaluation, while the client deadline also bounds updates and response decoding. Upgraded nodes must restart once so the managed Oxigraph child is relaunched with --timeout-s.
Blazegraph uses the same bounded/retryable DKG contract with backend-specific cancellation semantics. Its 30-second client deadline sends a wider 120-second X-BIGDATA-MAX-QUERY-MILLIS server bound: the wider server limit caps abandoned work without allowing Blazegraph's mid-stream timeout behavior to be mistaken for a complete CONSTRUCT result. Store admission pressure returns 503 STORE_SCHEDULER_BUSY with outcome: "not_started"; an adapter deadline returns 503 STORE_OPERATION_TIMEOUT, retryable: true, and outcome: "indeterminate". For an indeterminate write, retry the same Knowledge Asset name/idempotency key rather than creating a new asset.
On Linux hosts using systemd, memoryMaxMiB runs managed Oxigraph in a dedicated transient user scope with a finite hard limit and disables swap for that scope, so database pressure cannot spill into host swap and stall the node. Optional memoryHighMiB sets its soft reclaim threshold and must not exceed memoryMaxMiB. This keeps Oxigraph outside the DKG daemon service's cgroup, so a finite MemoryMax on the daemon cannot kill the store or throttle the Node.js control plane as one combined process group. Enable lingering once for the node service account (sudo loginctl enable-linger <dkg-user>) so its user manager and bus exist before the system service starts at boot; verify with systemctl --user is-system-running as that account. The daemon supplies the required user-bus environment automatically. Startup fails rather than silently dropping configured limits when the scope cannot be created.
Size the daemon service and Oxigraph scope independently, while keeping their combined maxima within host capacity. For example, an 8 GiB node can reserve 3 GiB for managed Oxigraph and place a separate finite 4 GiB cap on the DKG service, leaving roughly 1 GiB for the OS. These options are deliberately opt-in and are not supported on non-systemd platforms.
Other stores
Blazegraph: One URL for both query and update. Set only
queryEndpointor set both options to the same URL (e.g.http://127.0.0.1:9999/blazegraph/namespace/kb/sparql).Apache Jena Fuseki: Typically
http://host:3030/dataset/queryandhttp://host:3030/dataset/update.GraphDB, Neptune, Stardog: Use the vendor’s SPARQL query and update URLs; add
authif required.
Blazegraph provisioned by dkg init (Docker)
When you pick the blazegraph backend in dkg init and leave the URL blank, the CLI offers to provision a container itself. For new containers, the provisioner uses the pinned multi-architecture image and data path declared in blazegraph-image.json, stores the journal in a named Docker volume, and uses --restart unless-stopped. Blazegraph output uses Docker's compressed local log driver with a 4 GB rotation budget (200m × 20 files), so an unattended container cannot fill the host disk. The provisioner auto-bumps the host port if 9999 is taken and is idempotent — re-running dkg init against an already-provisioned namespace reuses the running container.
A reused legacy container is never recreated automatically, because doing so could discard its journal. If its volume or log policy does not match the current configuration, the CLI prints explicit backup/migration and unbounded-log warnings instead.
Programmatic (DKGAgent)
When creating an agent in code, pass storeConfig:
Store defaults
New installs default to a daemon-managed local Oxigraph server (store.backend: "oxigraph-server"): dkg init, dkg openclaw/hermes/mcp setup, or accepting the wizard default writes this block. The daemon fetches the pinned oxigraph binary on first boot and runs it on loopback, giving MVCC concurrent reads and incremental RocksDB persistence.
If a config has no store block at all, the runtime falls back to the embedded in-process oxigraph-worker (a single-writer store that rewrites its on-disk N-Quads dump under dataDir on every flush) — fine for development and small nodes. For very large graphs or existing infrastructure, use sparql-http with an external store.
Last updated
Was this helpful?