ArcadeDB 26.11.1 closes 887 issues and pull requests under the 26.11.1 milestone: 651 issues and 236 PRs, out of 483 pull requests merged and about 690 commits since 26.10.2. 468 of the closed issues are bug fixes, 28 of them rated critical.
At a Glance
| Area | What changed | The number |
|---|---|---|
| Transactions | A failed statement is taken back on its own and the transaction goes on; UPDATE ... SET reads the row as it was before the statement |
up to 100,000 entries per savepoint by default |
| Crash safety | Recovery after a power loss repairs torn pages and quarantines what it cannot recover; vector indexes are durable at READY |
found with Jepsen LazyFS |
| Vector search | Cypher 25 SEARCH, Neo4j’s CREATE VECTOR INDEX / CREATE FULLTEXT INDEX, PRODUCT and BINARY indexes search on their codes |
INT8 graph build 2.3x faster |
| Operations | Idle databases close and reopen on demand, a read-only database holds no WAL file, Claude Code plugin | native image about 25% faster at -O3 |
| Wire protocols | The PostgreSQL catalog answers psql, pgjdbc and psqlodbc; Redis pipelining | Redis at 0.8 to 0.9x of Redis on one connection |
| Security | Security files are never replaced by a default on a bad reload, plugin routes answer only their method, 401 on wrong credentials | see Security |
| Graph | A Cypher triangle count in one MATCH |
1,750 ms to 5 ms on a Graph Analytical View |
Upgrading is recommended for every deployment. This release changes several answers to be correct (SQL, Cypher temporals, string functions, HTTP status codes), changes the Docker user and drops the plain Kubernetes StatefulSet: read the upgrade checklist before you upgrade.
New Features
Vector and Full-Text Search
If you build retrieval on ArcadeDB, for example a GraphRAG pipeline that mixes vectors with graph traversal, this is the release that makes the Cypher side of it complete.
- Cypher 25
SEARCHclause (#10776, #10783). The vector search runs first and binds the variable to theknearest records. The innerWHEREis tested on each candidate during the search, which widens until it haskmatching rows, so a filtered search no longer comes back short. The clause used to be parsed and dropped, answering everyDoc. - Neo4j index DDL in openCypher (#10678, #10864, #10914, #10994, #10915, #10992).
CREATE VECTOR INDEXandCREATE FULLTEXT INDEXbuildLSM_VECTORandFULL_TEXTindexes, withIF NOT EXISTS,OPTIONSfrom a map or a parameter, several labels or relationship types (FOR (n:Article|Post)) under one logical name, and a vector index that takes its dimension from the first vector it receives.SHOW INDEXESlists acreateStatementthat runs as written. Requested by @chetto1983. If you are moving a Neo4j application over, the Neo4j alternative page shows how much of the rest of the surface is covered.
Here is the whole loop, as it runs on 26.11.1:
CREATE VECTOR INDEX doc_embedding IF NOT EXISTS
FOR (d:Doc) ON (d.embedding)
OPTIONS {indexConfig: {`vector.dimensions`: 768, `vector.similarity_function`: 'cosine'}}
MATCH (d:Doc)
SEARCH d IN (VECTOR INDEX doc_embedding FOR $query WHERE d.lang = 'en' LIMIT 10) SCORE AS score
RETURN d.title AS title, score
ORDER BY score DESC
IS :: VECTOR<T>(n)property type constraint, and avector(v, n, T)that builds the array of its coordinate type (#10862, #10918, #10917, #10991).- Pre-filter for
db.index.vector.queryNodes(#10685, #10808): an optional options map withwhereandfilter, tested during the search, so a multi-tenant query no longer returns fewer rows than asked.vector.neighborsandvector.sparseNeighborstake the samewhereoption, evaluated only on the candidates the search visits (#10169). PRODUCTandBINARYindexes search on their codes (#10514, #10968, #10975). The walk scores on the in-memory PQ codes (or the one-bit codes) and re-ranksk * rerankOversamplecandidates on the stored vectors, so the returned distances stay exact. New index settingsrerankOversampleandfusedPQ, a per-queryrerankoption, andpqTrainingLimitis now honored. APRODUCTgraph file is about 8x smaller.- Full-text filters decided before the load (#11069): a condition on another indexed property next to
SEARCH_INDEX()/SEARCH_FIELDS()is checked against that index first. WithLIMIT 10the reported query loads 10 records instead of about 2,000. Reported by @shaunpatterson.
Server and Operations
- Close idle databases and reopen them on demand (#11068). Off by default:
arcadedb.server.databaseIdleTimeoutcloses a database after that long without activity,arcadedb.server.maxOpenDatabaseskeeps at most that many open (least recently used first), and the next request over any protocol (HTTP, gRPC, PostgreSQL, Bolt, Gremlin, MCP) reopens it. A database with an open transaction, a running query or async work, or under HA, is never closed. This is the setting to reach for when one ArcadeDB server hosts a database per tenant. Requested by @singh-hovr. - WAL files and housekeeping on demand (#10234, #10218). One shared scheduler replaces a timer thread per database, and a WAL file is opened by the first commit that needs it and released after 60 s idle (
arcadedb.txWalIdleTimeout), so a database that is only read holds no WAL file. A background warm-up afterONLINEcuts the first HTTP query from about 160 ms to 60 ms (arcadedb.server.queryWarmUp). - Claude Code plugin (#11170). The ArcadeDB repository is now a Claude Code plugin marketplace:
claude plugin marketplace add ArcadeData/arcadedb --sparse .claude-plugin claude-plugin, thenclaude plugin install arcadedb@arcadedb, connects Claude Code to your own server with an API token. Every tool of the MCP server now carries read-only, destructive and open-world annotations, and thequeryandexecute_commandtools refuse scripting languages. - Native image: built at
-O3, about 25% faster on warm loops (#11070, contributed by @tae898); an explicit CPU baseline (x86-64-v3on amd64,armv8-aon arm64) documented in a “CPU requirements” section ofdocs/native-image.md(#10581, #10715); and a new linux/amd64-compatarchive built with-march=compatibilityfor CPUs below x86-64-v3 (#10623, #11253). arcadedb.txWalGroupCommit(opt-in): concurrent commits share one WAL flush, about 4x the commits per second for writers into the same type (#10499).arcadedb.fileSync(defaulttrue) skips every fsync when set tofalse, for test runs and throwaway databases; ArcadeDB’s own unit-test lanes now run twice as fast with it (#11149).arcadedb.graph.ghostEdgeProbe: a database known to hold no dangling adjacency entries can skip the per-vertex probe of variable-length walks (#10658).arcadedb.bucketSelfDescribingChunkLinks(opt-in, defaultfalse): the new chunk-link format that lets a multi-page record link position 0. A database that stored it cannot be read by an older version (#10853, #10949).
Query Languages and Engine
- Time series samples can be deleted (#10342, #10428).
DELETE FROM <ts type> WHERE <time range> [AND tag = value]andTRUNCATE TYPEremove samples from the mutable and the sealed storage, replicate under HA, and refresh the continuous aggregates over the type. For a real-time analytics workload that means a bad batch from one sensor can finally be removed without touching the rest:
DELETE FROM Reading
WHERE ts BETWEEN '2026-11-01 00:00:00' AND '2026-11-01 06:00:00'
AND sensor = 's1'
If you are new to the time series side of ArcadeDB, Time Series in ArcadeDB: Line Protocol to PromQL to Grafana walks through ingestion and querying end to end.
- Graph algorithms:
algo.personalizedPageRanktakesdirectionandweightProperty, andalgo.labelpropagationtakes pre-assigned labels (seedProperty,fixedSeeds) and refuses unknown keys (#11146, #11145, both reported by @chetto1983). - Statement-level savepoints (#10346), described in the highlights below.
sum()andavg()accept durations, in SQL too (#10198).
Studio
- The graph view keeps moving with live physics (node repulsion, edge springs, center gravity), as Neo4j Browser does (#10705, contributed by @shaunpatterson).
- Charts are drawn with Apache ECharts instead of ApexCharts, which stopped being open source; all six charts resize with their panel and follow the theme (#10579).
- The Add Index dialog has a Build Mode option (
SORTED) forLSM_TREEindexes (#10363); “Copy to clipboard” works on plain-http pages (#10239, reported by @pwitherton); the GraphML export carries vertex and edge properties (#11236). - A default
crudserver group fills the gap betweenadminandreadonly(#10778, contributed by @gramian).
Major Highlights
Transactions: a Failed Statement Is Taken Back, and SQL Reads Like SQL
- A statement that fails inside a transaction is undone on its own, and the transaction goes on (#10346, #10194, #10379). A multi-row
INSERT,UPDATE,DELETE,CREATE EDGE, openCypher orsqlscriptstatement that failed after writing part of its records used to leave them in the caller’s transaction, and the commit published half a statement. The engine now rolls the statement back the way SQLite does: its records, unique, plain, vector and full-text index entries (with the BM25 counters), edges and both vertices’ edge lists, page bytes, record counters and reserved slots. When it cannot be taken back exactly (abovearcadedb.txStatementSavepointMaxEntries, 100,000 by default, or a statement that touched a Graph Analytical View, dropped a file, or ran Gremlin), the commit is refused with aTransactionExceptionnaming the reason. UPDATE ... SETreads the row as it was before the statement, soUPDATE Pair SET a = b, b = aswaps the two values as in any SQL database, and an explicitNULLis stored asNULL: aDEFAULTfills only a property that is left out (#10194).CREATE INDEXno longer leaves out a record another session wrote and has not committed (#10588). That record stayed invisible to every index-backed query, and aUNIQUEindex accepted a duplicate of its key. A transaction that began before the index now queues the entries it owes the index at commit. With it,CREATE INDEXin a transaction that wrote to the indexed type no longer loses every committed record on rollback (#10490), and a refusedDROP INDEXno longer leaves the index half dropped (#10589).- A UNIQUE key moved off its holder can be given to only one record (#10265), a
NOTUNIQUE_HASHkey changed away and back no longer lists the record twice (#10269), and a compactedNOTUNIQUELSM index no longer returns entries its records do not have (#10188). - A failed
transaction()block that joined the caller’s transaction leaves it open instead of rolling back the caller’s earlier work (#10135), and deleting a missing or vetoed record over the remote drivers now throws (#10230). - An update of a record with an undecodable property is refused instead of saving the record back without that property (#10955), and an auto-commit gRPC
ExecuteCommandretries a transient conflict like HTTP does (#10942).
Crash Safety, Storage and High Availability
The Jepsen work moved on to LazyFS this cycle, which simulates a power loss by dropping whatever the disk had not synced. It found real problems, and they are fixed here.
- Power loss: crash recovery repairs torn pages whose earlier versions are still in the WAL, so a recovered node no longer returns records with wrong or missing property names (#11151, #11153). A database whose recovery did not complete is quarantined (
LOCAL_RECOVERY_INCOMPLETE,UNAVAILABLE_UNIQUE_INDEX) and resynced from the leader instead of serving half-recovered data (#11250). - Vector indexes are durable at
READY: a process killed right afterCREATE INDEXorREBUILD INDEXof anLSM_VECTORindex no longer reopens it empty or loses the transactions committed after it (#11238). CommittedLSM_SPARSE_VECTORpostings survive a crash through per-index posting logs, and every HA node answers with the postings the leader has not sealed yet (#11239, #11257). A full vector rebuild keeps the deletes and inserts committed while it reads the pages (#11099). - Records on a full page: growing a small record no longer writes its 9-byte pointer over the next record (#10617, #10637, #10669, #10859), a multi-page record can no longer be cut short at commit by a link to slot 0 of page 0 (#10701), and freeing a chunk chain no longer unlinks a live record (#10875).
- Restores: an overwrite restore extracts into a staging directory and keeps the old copy on failure, so a mistyped encryption key no longer destroys the target (#11050, #11058, #11041). While a restore replaces a database it refuses every write on every protocol, so nothing is acknowledged and then lost (#10689, #10533), and under HA it waits for the leader commits still replicating and refuses replica writes (#10881, #10965). A snapshot install checks the installed files against the leader’s account before the backup is deleted (#11200, #11223).
- HA: an index compaction whose publication has an unknown outcome quarantines the leader instead of leaving its index silently short (#11240); a refused
CREATE INDEX ... UNIQUEno longer quarantines the leader (#10506, #10569); eight apply-path failures no longer let the checkpoint move past an entry this node skipped (#10086); one Gremlin write sent to a follower is no longer applied several times (#11182); and a replicated apply publishes its pages under the publication sequence protocol (#10941). - A database opened
READ_ONLYwrites nothing when it closes (#10507), andschema.prev.jsonis a byte copy, never a hard link, so it stays readable on SeaweedFS and similar file systems (#11097).
Graph and openCypher Correctness
- Concurrent edge deletes no longer leave an edge list naming a deleted edge or a reused RID (#10263, #10304), a lightweight-edge delete after reading an outdated list is no longer lost (#10302, #10315), a super-node delete removes exactly one twin (#10314), and an edge-list
Iterator.remove()no longer loses its removal at commit (#10375). - A
MutableVertextaken bymodify()no longer saves a stale edge list over edges appended through another handle (#10929);DROP TYPErefuses an edge type whose edges are all lightweight (#10923, #11142); andREBUILD TYPE ... POLYMORPHIC WITH repartition = trueno longer rewrites subtype records as the scanned supertype (#11042, #11043, #11066). CHECK DATABASE FIXon a super-node no longer deletes its lightweight edges (#10377), and deleting a vertex no longer leaves its self-loop edge records behind (#10520).- openCypher: an explicit write of a lookup key makes the query eager, so a
MATCHfilter sees the graph as it was before the write (#11173, #11230); temporal values compare, add and construct as in Neo4j (#10198, #10199, #10200);DISTINCT,GROUP BY,UNION,min()andmax()keyBINARYandARRAY_OF_*values by content (#10380, #10195); dynamic labels inCREATE/MERGEare no longer dropped (#10683); and a long run of query-correctness reports from @YGY-001 is fixed (LIMIT 0afterWITH collect(),CALL { } IN TRANSACTIONSafter an empty batch,WITH *andFOREACHvisibility, among others: #10892, #10886, #10891, #10890, #10889, #10515, #10513, #10512, #11004, #11005, #11008). - Graph Analytical Views reach the commits in commit order (#10249), no longer count an edge twice after a background compaction (#11192), pin one snapshot per query (#10365), and need far less heap to build and restore: a 6M-edge view now builds in a 112 MB heap (#11011).
Time Series
- Deletes,
TRUNCATEand late samples keep continuous aggregates right on every ingest path (SQL, Java API, async, line protocol, Prometheus remote write, gRPC, JSONL importer), under HA too (#10502, #10686, #10632, #10633, #10634, #10673). WHERE ts > 9223372036854775807no longer overflows to the whole range, where aDELETEremoved every sample (#10528); a type rename moves the engine’s files (#10749);DROP TYPEserializes with a sealed-file merge (#10866, #10867); andCREATE TIMESERIES TYPErefuses a sealed file already at its name (#10925).- Cypher, Gremlin and GraphQL refuse a time series type instead of matching nothing (#10440, #10442), MongoDB QL reads it (#10468), and SQL
INSERTrefuses a number for aBOOLEANorSTRINGcolumn, as every other ingest path does (#10137).
Security
Authorization, input-bounds and hardening fixes found by audit and by reporters. The related GitHub security advisories are published with this release.
- MongoDB wire: a legacy
OP_QUERYon a collection no longer reaches documents without passing the authorization gate. - Per-type ACL: the first batch request to a closed database opened on demand now binds the per-type ACL; renaming a type with only
updateSchemano longer escapes the ACL of the type; three schema listings, the cluster endpoint and the gRPCgetDatabaseInfofilter what a user cannot read; and full-text BM25 statistics respect bucket access control. - Security file reloads (#10321, #10326, #10383, #10403, #10451, #10460, #10404): a malformed, missing or unreadable
server-users.jsonl,server-groups.jsonor API-token file on a running server keeps the users, groups and tokens in force instead of replacing them with a default (a passwordlessroot, the default groups), and keeps the bad file as an-errorcopy. A replicated change whose write failed is no longer undone by the watcher. - Read-only paths: on the native image, writes nested in a
SELECT(andPROFILE INSERT) no longer pass the read-only query paths; analyzing a Gremlin script no longer runs it, so the MCP read-only tool cannot commit a write (#11182); the MCP upsert tools honorallowSchemaChange, and MCP refusals no longer reveal which databases exist. - Plugin routes answer only the method they declare (#10157, #10296, #10385):
GET /api/v1/cluster/stepdownno longer steps the leader down, and a plugin can no longer silently replace another plugin’s route or a core route. - Authentication: wrong Basic credentials answer 401, not 403 (#10109); a failed Bolt
LOGONno longer leaves the previous principal bound; the snapshot endpoint no longer falls back to Basic credentials on a wrong cluster token (#10827); and a user’sresultSetLimitandreadTimeoutapply to that user only (#11248). - HA cluster token: a node refuses to start when the root password behind its derived cluster token changed, from the file or inline (#10601, #10924), and a sender can no longer force a Raft channel reset or take a throttle slot by naming this node in an unauthenticated header (#10144, #10225, #10299).
- Redis wire: an unauthenticated connection can no longer be held open at a trickle past the idle timeout, nor turn every junk byte into two SEVERE log records (40 KB of input wrote 6.2 MB of log) (#10597).
- Operator intent: a
/wssubscribe frame no longer reopens a database an operator closed (#10690).
Performance
The numbers below come from the issues that introduced each change. For how ArcadeDB compares with other engines on standard workloads, see the benchmarks.
- Graph: a Cypher triangle count written as one
MATCHtakes 5 ms on a Graph Analytical View and about 40 ms without one, where it took about 1,750 ms (#10255); variable-length hops with distinct endpoints walk the view, 6 hops going from 222 ms to 6 ms (#10548);algo.bfsstops atmaxDepth(#10539); andIN $listseeks the index with anOPTIONAL MATCH(#10354, contributed by @sainiteesh36). - Indexes and schema:
CREATE INDEX ... UNIQUEon a populated type is linear instead of quadratic (#10334), the sorted build runs beside pending writes to other types (#10466), and schema changes scale with the types (#10247). - Vectors: the
INT8/BINARYgraph build keeps the quantized rows instead of churning a float cache, 2.3x faster at 1M x 768 with about 50x less GC pause time (#10543);ARRAY_OF_FLOATSis stored fixed-width, 9 rows of 1536 dimensions per page instead of 7 (#10856); aPRODUCTrebuild keeps its PQ codebook (#10847) and reopens in 0.7 s instead of 2.6 s on 1M vectors (#10568); and hybrid queries load each candidate once (#10129). - Storage and allocation: a bucket insert no longer walks every slot of its page, which was 19% of the CPU of a small insert (#10576); LSM lookups share one page view, 36 to 41% less allocation (#10654); a filtered scan reuses its rejected rows (#10655); variable-length number reads allocate nothing (#10656); and
GraphBatchflushes one-bucket edge types in parallel (#10547). Several of these were contributed by @tae898. - Startup: the GraalVM polyglot engine is built only when a script language is used, so SQL and Cypher load no Truffle classes (#10245).
- PostgreSQL: a
SELECTof declared properties streams in chunks per fetch instead of being materialized whole (#6659, contributed by @GadiVenkatesh). - Redis: pipelined replies are sent together (from 0.35x to 0.8 to 0.9x of Redis on one connection, and about 2x Redis with 200 connections), and in-memory commands bypass the query admission gate (#10499).
Major Fixes and Improvements
Wire Protocols
- PostgreSQL catalog: psql
\dt,\d,\d+,\di,\dm,\df,\duand psqlodbcSQLColumns/SQLTablesanswer from the emulated catalog (#10228, #10473, #10691, #10591);pg_index,pg_depend,pg_matviews,pg_settingsand the JDBC type lookups are modeled (#10473, #10495, #10842, #10961); a statement that merely containedpg_catalogin a literal is executed again (#10695); a connection re-resolves its database after a close, restore or drop (#10692); text-format array parameters keep empty andNULLelements (#10870); andformat_type()andregtypeprint PostgreSQL’s names (#10228). - Redis: a key starting with
$is no longer the same key as the one without it (#10694), inline commands are answered (#10597), and a command whose name is not a string gets an error instead of silence (#10845). - MongoDB: every command uses the instance currently open after a restore or reopen (#10562), and writes on a time series collection are refused unless applied exactly (#10464).
- gRPC: graph projections and lists of a search hit arrive typed instead of as a Java
toStringor a JSON string (#11044, #11048, #11207),BeginTransactionrefusesSERIALIZABLE(#10386), and authentication faults are logged and counted (grpc.auth.faults.total) (#10142). - A closed database is reported as unavailable, not as a server fault, on every wire protocol: PostgreSQL
57P03, RedisLOADING, MongoDBTemporarilyUnavailable, gRPCUNAVAILABLE, BoltDatabaseUnavailable(#10553, #10692). - HTTP: committing a session the server does not hold answers 404 instead of 204 (#10164);
POST /api/v1/beginvalidatesisolationLevel(#10295, #10337); and the OpenAPI document works on the native image (#10573) and is accurate for the group listing (#11276).
SQL and Functions
- String methods count Unicode characters, not UTF-16 code units, in SQL and openCypher (#10248, #10378, #10523, #10524).
=,<>,INandCONTAINScompare list and map elements as they compare scalars (#10595, #10448);DISTINCT,GROUP BY,min()andmax()compareBINARY, array, map and temporal values the way=does (#10696, #10697, #10710).- A
DATETIMEstring with an offset is stored as the UTC wall clock of the instant (#10489, #10596); a number into aDATEis a day count under everydateImplementation(#10910); and invalid dates such as2021-02-30are refused (#10206). - On an edge,
outandinread the endpoints (#10684);shortestPath()maxDepthcounts edges (#10439), anddijkstra()/astar()bound the path (#10527);if,randomInt,pow()and the Cypher-style functions no longer truncate or wrap a number argument (#10699, #10850, #11047); and positional and named parameters are counted, so an unbound placeholder is refused (#10721, #11098). INSERT INTO T FROM SELECT ... FROM Tno longer reads its own inserts (#10192), triggers fire for subtype records (#10207),REFRESH INCREMENTALviews follow writes to subtypes and joined types (#10205), and a refused schema statement changes nothing (#10317, #10412).
Packaging and Deployment
- Every Docker image (JVM, native and custom distribution) runs as
1000:1000and declares the same five volumes (#10319, #10330, #10387), and the compose quickstart persists all of them (#10402). - The Helm chart is the only supported Kubernetes deployment (#10542); Deploy an ArcadeDB Cluster on Kubernetes with Helm shows the setup. A config directory moved off
<root>/config, or a volume mounted over it, is seeded with the shipped defaults (#10536, #10554), and an HA node started with onlyarcadedb.server.rootPasswordPathforms a cluster (#10462). - The native image creates
GEOSPATIALindexes (#10423) and ships a parseable users template (#10320).
Importers and Remote Clients
- JSONL
EXPORT/IMPORT DATABASEround-trips declaredLIST/MAP OF DATE,BINARY,DOUBLEand record links (#10201, #10391, #10483, #10529); the JSON importer keeps integers and longs exact (#10756); and GraphSON and GraphML export every property type (#10202). - The Java HTTP client reads
+/-InfinityandNaNfloats (#10899), sends aLocalDateparameter as a typed marker and readsLIST OF DATEitems back asLocalDate(#10865, #10908, #10909, reported by @TobiasJoseHermann). - Studio’s record editor no longer discards edits or retypes untouched properties on save (#10082, #10083).
Build and CI
- CI runs Maven through
./mvnw, the slow and HA lanes run in parallel shards, and the CI wall time dropped from 43 to 26 minutes (#10134, #11154, #11183, #11189, #10887, contributed by @agarg21). Census tests enumerate from the authority they protect (#11199, #10982, contributed by @2748109647).
Upgrade Checklist
Behavior changes are collected in the release notes, and the complete write-up is in docs/release-26.11.1.md. The ones worth checking before you upgrade:
- Docker images run as UID 1000 (#10319, #10330). A volume written by an earlier native image (root on amd64, 65532 on arm64) or custom-distribution image (
100:101) must be handed over once withchown -R 1000:1000 <path>. Custom images now declareconfigandreplicationas volumes, and the compose quickstart mounts a named volume on all five: copy users, groups and tokens out of the old anonymousconfigvolume before recreating the stack (#10387, #10402). - Kubernetes:
config/arcadedb-statefulset.yamlis no longer shipped; move to the Helm chart at ArcadeData/arcadedb-helm (#10542). - HA cluster token: with a token derived from the root password (file or inline), the password can no longer be rotated with a rolling restart. Restart every node once with
arcadedb.ha.clusterTokenAllowRotation=true, or usearcadedb.ha.clusterTokenPath(#10601, #10924). - HTTP status codes: wrong Basic credentials answer 401 (was 403) (#10109); committing an unknown or foreign session answers 404 (was 204) (#10164); plugin routes answer 405 on an undeclared method, and
registerAPI(HttpServer, PathHandler)is deprecated for removal (#10157, #10296); a plugin route that collides with another plugin’s or a core route fails the server start (#10385). - Transactions: a failed statement inside a transaction is taken back and the commit publishes the rest (#10346); a failed joined
transaction()leaves the caller’s transaction open (#10135);UPDATE ... SETreads the pre-statement row and an explicitNULLis stored asNULL, so aNOTNULLproperty with a default refuses it (#10194). - SQL and openCypher answers that changed:
- string functions count characters, not UTF-16 code units (#10248, #10378);
- Cypher durations are not comparable with
</>, alocaldatetime()is not adatetime(), duration arithmetic is exact and calendar units follow the local calendar (#10198, #10199, #10200); - a
DATETIMEstring with an offset is stored as UTC (values already stored are not rewritten), andasDateTime(format)/date(value, format)follow (#10489, #10596); - list and map elements compare as scalars, so
[1] = ['1']istrue(#10595); on an edgeout/inare the endpoints (#10684);shortestPath()maxDepthcounts edges, so lower it by one if you raised it as a workaround (#10439); - a fractional or out-of-range integer argument is refused by
if,randomInt,vector.sparseCreateand the Cypher-style functions (#10699, #10850, #10954); - a number into a
DATEis a day count under everydateImplementation(#10910), an impossible date such as2021-02-30is refused, and aDATEcompared with aDATETIMEis midnight of that day (#10206); - a SQL statement given more or fewer parameter values than it has placeholders is refused instead of dropping or binding
null(#10721, #11098); - Cypher, Gremlin and GraphQL fail on a time series type instead of matching nothing (#10440, #10442), and SQL
INSERTinto a time series refuses a number for aBOOLEANorSTRINGcolumn (#10137).
- Indexes and storage: a transaction that gives one UNIQUE key to two records now fails (#10265); an update of a record with an undecodable property is refused (#10955); a
PRODUCTvector index ranks through PQ codes and re-ranks, so raisererankorrerankOversampleif recall matters more than speed (#10514). - Remote drivers: deleting a missing or vetoed record throws
RecordNotFoundException/RecordVetoedException(#10230); aLocalDateparameter is sent as a typed marker, so upgrade client and server together (#10908); gRPCBeginTransactionrefusesSERIALIZABLE(#10386). If you run ArcadeDB embedded in a JVM application, check the transaction changes above before you bump the dependency. - Wire protocols: PostgreSQL
format_type()andregtypeprintintegerandcharacter varying(#10228); Redis closes a connection on a malformed message (#10597); MongoDB refuses updates and inexact deletes on a time series collection (#10464). - HA: a compaction publication with an unknown outcome quarantines and resyncs the leader (#11240).
A result set that changes after the upgrade is the fix, not a regression.
Dependency Updates
About 75 dependency bumps landed in this cycle, almost all through Dependabot. The notable ones:
- Server and engine: gRPC 1.84.0, GraalVM Polyglot 25.4, jvector 4.0.2 (native vectorization off unless configured), Jackson 2.22.4, Micrometer 1.17.2, OpenTelemetry 1.67.0, Logback 1.6.6, Gson 2.15.0, jboss-threads 3.11.1, lz4-java 1.12.1, snappy-java 1.1.10.12, JLine 4.4.8 and swagger 3.0.0. Guava is pinned to 33.7.2-android (CVE-2026-102554) (#11237).
- Studio: Apache ECharts replaces ApexCharts, d3-force drives the live graph physics, cytoscape 3.34.4 and swagger-ui-dist 5.34.0; JSZip and the PDF export are gone, and the license check now fails the build on a package outside the allow-list (#10579, #10626).
- Build and test: Surefire/Failsafe 3.6.1, JaCoCo 0.8.16, GraalVM native-maven-plugin 1.1.16, ASM 9.11.1, testcontainers, the Neo4j drivers of the e2e suites and the Go module bumps.
- CI: GitHub Actions and pre-commit hook bumps.
Getting Started with 26.11.1
Docker
docker pull arcadedata/arcadedb:26.11.1
Visit our Docker Hub repository for more information.
Maven
<dependency>
<groupId>com.arcadedb</groupId>
<artifactId>arcadedb-engine</artifactId>
<version>26.11.1</version>
</dependency>
All artifacts are available on Maven Central.
Documentation
For details on features and usage, see the documentation.
Download ArcadeDB 26.11.1 now: GitHub Releases
Thanks to everyone who reported, reproduced, reviewed, tested and fixed, in particular @ruispereira, @tae898, @YGY-001, @chetto1983, @ItsDeadlyProgrammer, @shaunpatterson, @neomodular, @sainiteesh36, @YaeSakuraQ, @GadiVenkatesh, @agarg21, @gramian, @7487, @2748109647, @pwitherton, @TobiasJoseHermann, @FilBr, @singh-hovr, @shulei5831sl and @FEARIS2.
Luca Garulli ArcadeDB Founder