gRPC API

ArcadeDB exposes a gRPC interface for high-performance, strongly-typed access from any language with gRPC support (Java, Python, Go, C++, Node.js, Rust, C#, and more). The gRPC API provides two services with 65 RPCs covering queries, record operations, transactions, graph bulk loading, vector and full-text search, time series, and server administration.

Proto definition: arcadedb-server.proto

Enabling the gRPC server

The gRPC module is bundled in the full distribution, but the server is implemented as a plugin (com.arcadedb.server.grpc.GrpcServerPlugin) that is not started by default. If the server is not listening on any gRPC port, it is because the plugin has not been registered yet.

Enable it by adding the plugin to the arcadedb.server.plugins setting, then start the server:

-Darcadedb.server.plugins=gRPC:com.arcadedb.server.grpc.GrpcServerPlugin

The format is <pluginName>:<pluginFullClass> (comma-separated when registering several plugins). Once enabled, the server listens on port 50051 by default. Confirm it started by looking for a gRPC server started line in the server log, or with grpcurl -plaintext localhost:50051 list.

Host, port, TLS, message size and the other gRPC options are configured through arcadedb.grpc. system properties - see gRPC settings for the full list. These plugin-level options are read as JVM system properties (-Darcadedb.grpc.) and, unlike arcadedb.server.plugins, are not resolved from environment variables.

Services

ArcadeDbService

The main service for database operations: querying, record CRUD, bulk inserts, transactions, graph bulk loading, search, and time series.

RPC Request Response Description

StreamQuery

StreamQueryRequest

stream QueryResult

Execute a query and stream results back row by row

ExecuteCommand

ExecuteCommandRequest

ExecuteCommandResponse

Execute a DDL/DML command (CREATE, INSERT, UPDATE, DELETE)

ExecuteQuery

ExecuteQueryRequest

ExecuteQueryResponse

Execute a query and return all results at once

CreateRecord

CreateRecordRequest

CreateRecordResponse

Create a new record (vertex, edge, or document)

UpdateRecord

UpdateRecordRequest

UpdateRecordResponse

Update an existing record by RID

LookupByRid

LookupByRidRequest

LookupByRidResponse

Look up a record by its Record ID

DeleteRecord

DeleteRecordRequest

DeleteRecordResponse

Delete a record by RID

BulkInsert

BulkInsertRequest

InsertSummary

Insert multiple records in a single request

InsertStream

stream InsertChunk

InsertSummary

Client-streaming insert for large datasets

InsertBidirectional

stream InsertRequest

stream InsertResponse

Bidirectional streaming for insert with per-record feedback

BeginTransaction

BeginTransactionRequest

BeginTransactionResponse

Begin an explicit transaction

CommitTransaction

CommitTransactionRequest

CommitTransactionResponse

Commit the current transaction

RollbackTransaction

RollbackTransactionRequest

RollbackTransactionResponse

Roll back the current transaction

GraphBatchLoad

stream GraphBatchChunk

GraphBatchResult

Client-streaming bulk load of vertices and edges (see below)

VectorSearch

VectorSearchRequest

VectorSearchResponse

Since 26.10.1. k-nearest-neighbor search over a dense or sparse vector index

HybridSearch

HybridSearchRequest

HybridSearchResponse

Since 26.10.1. Fused vector, full-text, and graph-expansion search

FullTextSearch

FullTextSearchRequest

FullTextSearchResponse

Since 26.10.1. Lucene-syntax search over a FULL_TEXT index

TimeSeriesWrite

TimeSeriesWriteRequest

TimeSeriesWriteSummary

Since 26.10.1. Write a batch of time-series points

TimeSeriesWriteStream

stream TimeSeriesWriteChunk

TimeSeriesWriteSummary

Since 26.10.1. Client-streaming time-series ingest

TimeSeriesQuery

TimeSeriesQueryRequest

stream TimeSeriesQueryResult

Since 26.10.1. Range query, raw or aggregated into buckets, streamed back

TimeSeriesLatest

TimeSeriesLatestRequest

TimeSeriesLatestResponse

Since 26.10.1. Latest sample of a time-series type, optionally filtered by tags

Graph batch load

GraphBatchLoad streams GraphBatchChunk messages, each carrying GraphBatchRecord entries of kind VERTEX or EDGE. The first chunk must name the database and carry the GraphBatchOptions (batch size, light edges, WAL, commit frequency, vertex_batch_size, commit retries, and return_id_mapping); options on later chunks are ignored. Vertices declare a temp_id, and edges reference their endpoints by temp_id or by an existing RID (#bucket:pos) in from_ref / to_ref. All VERTEX records must precede every EDGE record across the whole stream: interleaving is an error. On a replicated cluster the load must run on the leader; a follower refuses it.

GraphBatchResult reports vertices_created, edges_created, elapsed_ms and, depending on return_id_mapping, the temp_id to RID map in id_mapping (when the map is not returned, id_mapping_omitted is set and id_mapping_size still reports its size). The load commits incrementally, so a failure is not a rollback: the counts already durable at the point of failure travel in the arcadedb-graph-batch-result-bin trailer of the failed call, with partial_commit set.

Since 26.10.1. These three unary RPCs run the same server-side implementation as the HTTP /api/v1/vector/* routes and the MCP search tools, so a request that is legal on one protocol is legal on all of them and is rejected with the same message. Every hit is a SearchHit with rid, record, and either distance (dense index, lower is better) or score (sparse, full-text, or fused, higher is better); the response’s scoring field says which.

RPC Key request fields

VectorSearch

index_name (an LSM_VECTOR index, or an LSM_SPARSE_VECTOR index when sparse is set), query_vector, query_indices (sparse dimension ids), k (1 to 1000, default 10), ef_search (dense only), filter (read-only SQL WHERE predicate applied to a bounded candidate window). ArcadeDB does not generate embeddings.

HybridSearch

The vector fields above (vector_index_name instead of index_name), plus an optional full-text leg (fulltext_query and fulltext_index_name, which must be given together), fusion_strategy (RRF by default, DBSF, or LINEAR), per-leg weights (keys vector, fulltext, expand), and an optional expand graph leg (edge_types, direction out/in/both, max_depth 1 to 3). The expand leg requires RRF.

FullTextSearch

query_text (Lucene syntax, not blank), the index addressed by index_name or by type_name plus optional properties (index_name wins when both are set), and limit (1 to 1000, default 10).

All three accept an optional transaction: when it names a live transaction the search reads exactly what that transaction reads, including its uncommitted changes. A transaction id the server no longer knows is refused with FAILED_PRECONDITION. See also Full-text index.

Time series

Since 26.10.1. The time-series RPCs read and write TIMESERIES types (see Time series).

  • TimeSeriesWrite / TimeSeriesWriteStream: each TimeSeriesPoint carries type (the measurement, defaulting to the request or chunk type), timestamp, and tags / fields maps of GrpcValue. precision defaults to TS_PRECISION_MILLISECONDS (unlike the HTTP line-protocol endpoint, which defaults to nanoseconds). The streaming variant needs database on the first chunk only and applies back-pressure, pulling one chunk at a time. A write is not atomic: each measurement’s batch commits as it is appended. TimeSeriesWriteSummary reports received, written, and dropped (written + dropped == received), and lists dropped points' types under unknown_types, non_time_series_types, or unavailable_types.

  • TimeSeriesQuery: type, inclusive from_timestamp / to_timestamp (unset means unbounded), fields projection (an unknown name is refused with INVALID_ARGUMENT), tags (TimeSeriesTagFilter, a conjunction of equality predicates on TAG columns; a non-TAG name is refused with INVALID_ARGUMENT), limit, batch_size (rows per streamed message, default 1000), and optional aggregation (bucket_interval_ms > 0, at least one TimeSeriesAggregationRequest of TS_AGG_SUM, AVG, MIN, MAX or COUNT, and an optional bucket_origin_ms). The answer streams as TimeSeriesQueryResult messages carrying rows (raw) or buckets (aggregated); the last message has last set, and truncated when the limit cut the answer short. The server-side ceiling arcadedb.server.grpcTimeSeriesMaxResultRows (default 1000000) cannot be raised by the client: a limit above it is refused with RESOURCE_EXHAUSTED before the first message.

  • TimeSeriesLatest: type and optional tags. TimeSeriesLatestResponse returns columns, found, and the latest row (unset when found is false).

TimeSeriesQuery and TimeSeriesLatest accept an optional transaction; when set, the read sees that transaction’s uncommitted points. An unresolvable transaction id is refused with FAILED_PRECONDITION (the HTTP time-series read routes instead fall back to reading outside the transaction).

ArcadeDbAdminService

Administration service for server and database management. Every admin RPC runs the same implementation as the HTTP control plane, so the two protocols behave the same way.

Authentication and authorization. Every request is authenticated from its credentials field, except Health and Ready, which are unauthenticated like GET /api/v1/health and GET /api/v1/ready. Ping, GetServerInfo, ListDatabases, ExistsDatabase, and GetDatabaseInfo need any valid account; GetProgress needs an account granted the named database; every other RPC requires the root user and otherwise fails with PERMISSION_DENIED.

Leader routing. On a replicated cluster, CreateDatabase, DropDatabase, CreateUser, UpdateUser, DeleteUser, SaveGroup, DeleteGroup, CreateApiToken, DeleteApiToken, RestoreBackup, RestoreDatabase, and ImportDatabase are refused on a follower with FAILED_PRECONDITION and the leader’s address in the arcadedb-leader-* trailers. gRPC has no request proxy, so the client redirects itself.

Server info and databases

RPC Request Response Description

Ping

PingRequest

PingResponse

Health check

GetServerInfo

GetServerInfoRequest

GetServerInfoResponse

Server version, uptime, and configuration

ListDatabases

ListDatabasesRequest

ListDatabasesResponse

List all databases

ExistsDatabase

ExistsDatabaseRequest

ExistsDatabaseResponse

Check if a database exists

CreateDatabase

CreateDatabaseRequest

CreateDatabaseResponse

Create a new database (see below)

DropDatabase

DropDatabaseRequest

DropDatabaseResponse

Drop an existing database (see below)

OpenDatabase

OpenDatabaseRequest

OpenDatabaseResponse

Since 26.10.1. Open the named database

CloseDatabase

CloseDatabaseRequest

CloseDatabaseResponse

Since 26.10.1. Close the named database’s open instance; the files stay, and a later request reopens it

AlignDatabase

AlignDatabaseRequest

AlignDatabaseResponse

Since 26.10.1. Run ALIGN DATABASE on the named database

GetDatabaseInfo

GetDatabaseInfoRequest

GetDatabaseInfoResponse

Schema, types, and database statistics

GetProgress

GetProgressRequest

GetProgressResponse

Since 26.10.1. Long-running operations (CHECK DATABASE, REBUILD INDEX, backup, import, …​) running on the database, as GET /api/v1/progress/{database}. Empty when nothing runs

CreateDatabase and DropDatabase answer the no-op case the way the HTTP create database and drop database commands do: a name already taken is refused with ALREADY_EXISTS, a name that does not exist with NOT_FOUND. Set if_not_exists on CreateDatabaseRequest, or if_exists on DropDatabaseRequest, to make the call idempotent instead. Either way the response says what happened: CreateDatabaseResponse.created is true only when this call created the database, and DropDatabaseResponse.dropped only when it dropped one, so a provisioning tool can tell "created for me" from "already there" rather than reading an empty OK as ownership. Database names are exact and never case-folded. The Java client exposes the two forms as createDatabase / createDatabaseIfMissing and dropDatabase / dropDatabaseIfExists; the IfMissing / IfExists variants return the boolean.

Users, groups, and API tokens

RPC Request Response Description

CreateUser

CreateUserRequest

CreateUserResponse

Create a new user

UpdateUser

UpdateUserRequest

UpdateUserResponse

Since 26.10.1. Update a user’s password and/or databases grants. Each field is optional and an absent one is left untouched; a present but empty databases clears the grants

DeleteUser

DeleteUserRequest

DeleteUserResponse

Delete a user

ListUsers

ListUsersRequest

ListUsersResponse

Since 26.10.1. List users with their per-database groups. Password hashes are never included

ListGroups

ListGroupsRequest

ListGroupsResponse

Since 26.10.1. The whole group document, as JSON in groups_json

SaveGroup

SaveGroupRequest

SaveGroupResponse

Since 26.10.1. Create or replace one group of a database (* for all) from group_json

DeleteGroup

DeleteGroupRequest

DeleteGroupResponse

Since 26.10.1. Delete one group of a database

ListApiTokens

ListApiTokensRequest

ListApiTokensResponse

Since 26.10.1. List API tokens as ApiTokenInfo (hash, last four characters, expiry, expired flag), never the token itself

CreateApiToken

CreateApiTokenRequest

CreateApiTokenResponse

Since 26.10.1. Mint an API token. The plaintext token is returned once only. Refused with FAILED_PRECONDITION unless the channel uses TLS or the client is on loopback; a duplicate name is ALREADY_EXISTS

DeleteApiToken

DeleteApiTokenRequest

DeleteApiTokenResponse

Since 26.10.1. Revoke a token by its token_hash (the plaintext token is not accepted)

Settings

RPC Request Response Description

SetServerSetting

SetServerSettingRequest

SetServerSettingResponse

Since 26.10.1. Set a server setting. key and value are separate fields, so a value with spaces needs no quoting

SetDatabaseSetting

SetDatabaseSettingRequest

SetDatabaseSettingResponse

Since 26.10.1. Set a setting of one database

Backup, restore, and import

RPC Request Response Description

GetBackupConfig

GetBackupConfigRequest

GetBackupConfigResponse

Since 26.10.1. Auto-backup configuration as JSON, and whether the auto-backup plugin is running

SetBackupConfig

SetBackupConfigRequest

SetBackupConfigResponse

Since 26.10.1. Save the auto-backup configuration from config_json

ListBackups

ListBackupsRequest

ListBackupsResponse

Since 26.10.1. Backup archives of a database, with retention totals

TriggerBackup

TriggerBackupRequest

TriggerBackupResponse

Since 26.10.1. Back up a database now; returns the archive path

DeleteBackup

DeleteBackupRequest

DeleteBackupResponse

Since 26.10.1. Delete one archive by plain file name (path separators and traversal are refused)

RestoreBackup

RestoreBackupRequest

stream RestoreProgress

Since 26.10.1. Restore a database’s backup archive into target_database; overwrite replaces an existing target only after the restore succeeded

RestoreDatabase

RestoreDatabaseRequest

stream RestoreProgress

Since 26.10.1. Create a new database from an archive at a url

ImportDatabase

ImportDatabaseRequest

stream ImportProgress

Since 26.10.1. Create a new database and import the source at a url into it; progress carries importer lines and parsed / vertices / edges counters

The three restore and import RPCs are server-streaming: they send progress messages while the operation runs, then one final message with completed = true (ImportProgress.result_json carries the importer’s final report). A failure ends the stream with an error status instead. Cancelling the call stops the progress messages, not the operation. Unless arcadedb.server.restoreImportAllowLocalUrls is enabled, only http/https URLs to non-private hosts are accepted. See also Backup.

Query profiler

RPC Request Response Description

ProfilerStart

ProfilerStartRequest

ProfilerStateResponse

Since 26.10.1. Start recording. timeout_seconds of 0 or less applies the server default; the effective timeout is returned

ProfilerStop

ProfilerStopRequest

ProfilerDocumentResponse

Since 26.10.1. Stop recording and return the run as JSON

ProfilerReset

ProfilerResetRequest

ProfilerStateResponse

Since 26.10.1. Reset the profiler

ProfilerResults

ProfilerResultsRequest

ProfilerDocumentResponse

Since 26.10.1. Current profiler results as JSON, without stopping

ProfilerList

ProfilerListRequest

ProfilerListResponse

Since 26.10.1. Saved profiler runs on disk, newest first

ProfilerLoad

ProfilerLoadRequest

ProfilerDocumentResponse

Since 26.10.1. Load a saved run by file name

Server lifecycle and cluster

RPC Request Response Description

GetServerEvents

GetServerEventsRequest

GetServerEventsResponse

Since 26.10.1. Server events as a JSON array, from the current event file or a named one, plus the list of event files

Shutdown

ShutdownRequest

ShutdownResponse

Since 26.10.1. Shut down this server (empty server_name) or the named HA peer. The local shutdown is scheduled asynchronously, so the response arrives first

DisconnectCluster

DisconnectClusterRequest

DisconnectClusterResponse

Since 26.10.1. Disconnect this server from the cluster

ConnectCluster

ConnectClusterRequest

ConnectClusterResponse

Since 26.10.1. Join the server at server_address (an arcadedb.ha.serverList entry) to the cluster. FAILED_PRECONDITION when HA is not running or cannot change membership at runtime; empty address is INVALID_ARGUMENT

ListSessions

ListSessionsRequest

ListSessionsResponse

Since 26.10.1. Open HTTP authentication sessions, including their bearer tokens. Enable TLS before calling it across an untrusted network

Health probes

RPC Request Response Description

Health

HealthRequest

HealthResponse

Since 26.10.1. Unauthenticated liveness probe; ok is false only when the HA layer escalated a crash loop

Ready

ReadyRequest

ReadyResponse

Since 26.10.1. Unauthenticated readiness probe; a not-ready node answers ready = false with a reason rather than an error status

Message Types

Connection & Authentication

DatabaseCredentials

Database name, username, and password for per-request authentication

Value Types

The GrpcValue message uses a oneof to represent any ArcadeDB value:

Field ArcadeDB Type

bool_value

Boolean

int32_value

Integer

int64_value

Long

float_value

Float

double_value

Double

string_value

String

bytes_value

Binary / byte array

timestamp_value

Datetime (google.protobuf.Timestamp)

list_value

List / array

map_value

Map / embedded document

link_value

RID reference (bucket:position)

decimal_value

Decimal (string-encoded)

null_value

Null

GrpcRecord wraps a record with its RID, type name, and a map of property name to GrpcValue.

Enums

Enum Values

RetrievalMode

CURSOR (streaming), MATERIALIZE_ALL (all at once), PAGED (paginated)

ProjectionEncoding

PROJECTION_AS_LINK, PROJECTION_AS_MAP, PROJECTION_AS_JSON

TransactionIsolation

READ_UNCOMMITTED, READ_COMMITTED, REPEATABLE_READ, SERIALIZABLE

ConflictMode

CONFLICT_ERROR, CONFLICT_UPDATE, CONFLICT_IGNORE, CONFLICT_ABORT

TransactionMode

PER_REQUEST, PER_BATCH, PER_STREAM, PER_ROW, NONE

PAGED retrieval keeps the ORDER BY your query specifies. When the query specifies none, rows are ordered by @rid, because cutting pages needs a stable order or a row could be skipped or repeated across pages. PAGED also reserves the parameter names _skip and _limit, and applies to SQL only: a query in another language falls back to CURSOR. If you order by a column with duplicate values, rows that tie can still move between pages, since every page re-runs the query; add a unique tie-break such as ORDER BY createdAt DESC, @rid when pages must be reproducible.

Insert Operations

BulkInsertRequest

Batch of records with type name, properties, and insert options

InsertChunk

A chunk of records for client-streaming inserts

InsertRequest / InsertResponse

Per-record request/response for bidirectional streaming

InsertSummary

Result summary: total inserted, errors, duration

InsertOptions

Transaction mode, conflict handling, and batch size configuration

Command Results & Write Statistics

ExecuteCommand returns an ExecuteCommandResponse:

Field Meaning

success / message

Whether the command succeeded, and an optional message

affected_records

Server-computed count of affected elements and numeric scalars

execution_time_ms

Server-side execution time

records

Optional row payload, returned when return_rows is set on the request

stats

A QueryUpdateStats message, present only for write commands that mutated data

QueryUpdateStats carries the same write counters the HTTP stats object and the Bolt result summary expose, including counts aggregated across OpenCypher UNION branches and CALL { …​ } subqueries:

Field Meaning

nodes_created / nodes_deleted

Vertices created / deleted

relationships_created / relationships_deleted

Edges created / deleted

properties_set

Properties assigned a value

labels_added / labels_removed

Type/label memberships added / removed

indexes_added / indexes_removed

Indexes created / dropped

constraints_added / constraints_removed

Constraints added / removed

contains_updates

true when any counter above is non-zero

The equivalent HTTP response object is documented at Write statistics.

Connecting from Python

import grpc
import arcadedb_server_pb2 as pb
import arcadedb_server_pb2_grpc as rpc

channel = grpc.insecure_channel('localhost:50051')
stub = rpc.ArcadeDbServiceStub(channel)

# Execute a query
request = pb.ExecuteQueryRequest(
    credentials=pb.DatabaseCredentials(
        database='mydb', username='root', password='arcadedb'
    ),
    language='sql',
    command='SELECT FROM V LIMIT 10',
)
response = stub.ExecuteQuery(request)
for record in response.records:
    print(record)

Connecting from Node.js

const grpc = require('@grpc/grpc-js');
const protoLoader = require('@grpc/proto-loader');

const packageDef = protoLoader.loadSync('arcadedb-server.proto');
const proto = grpc.loadPackageDefinition(packageDef).arcadedb;

const client = new proto.ArcadeDbService(
  'localhost:50051', grpc.credentials.createInsecure()
);

client.ExecuteQuery({
  credentials: { database: 'mydb', username: 'root', password: 'arcadedb' },
  language: 'sql',
  command: 'SELECT FROM V LIMIT 10',
}, (err, response) => {
  console.log(response.records);
});

Further Reading