Skip to content
Published on

A Mid-Course Check on Neo4j's CalVer Era: Block Format, Cypher 25, and How GQL Lands in the Engine

Share
Authors

Introduction — Not RAG, the Engine

On this blog, graphs have mostly shown up as raw material for RAG lately — What Is Graph RAG and The Tools for Running Graph RAG are that thread. Today we go one layer down. Quite a lot has quietly happened over the past year and a half at the database engine layer that actually stores the graph and runs the queries.

The stage is mostly Neo4j. Like it or not, it's the default for server-based property graphs (see A 2026 Survey of the Graph DB Landscape), and more to the point, three transitions are happening in this engine at once right now. The release model changed (calendar versioning), the storage default changed (block format), and the language gained versions (Cypher 5 vs. Cypher 25 — and the ISO GQL standard behind it). None of the three is a "press upgrade and you're done" change; each requires an operational judgment call.

Every version, date, and policy claim below was checked directly against Neo4j's official changelogs, docs, the support-policy page, and endoflife.date, with sources linked inline.

The Release Model — Ships Every Month, Support Ends the Next Month

Neo4j ended semantic versioning at 5.26 and switched to calendar versioning. Per Neo4j's history on endoflife.date, the first CalVer release, 2025.01, shipped in early February 2025, and by 2026.06 (GA on July 8, 2026) about 17 months later, 18 feature releases had accumulated — roughly one a month.

What matters isn't the pace but the support policy. Neo4j's official supported-versions doc states that hotfix availability for each release runs "generally until the next minor release ships." The actual table bears this out — hotfixes for 2026.05 end the moment 2026.06 ships. In other words, the effective lifespan of a single CalVer release is 4–6 weeks.

TrackVersionStatus (as of 2026-07-17)
LTS4.4EOL 2025-11-30
LTS5.26 (2024-12-06)Hotfixes through 2028-06-06, latest patch 5.26.28 (2026-06-30)
CalVer train2025.01 – 2026.06Only the latest release is supported; older ones lose support immediately

And as of this writing, the CalVer line has no LTS at all. Neither the supported-versions doc nor endoflife.date marks any 2025.x or 2026.x release as LTS. That leaves self-managed deployments with exactly two options.

  • Stay on 5.26 LTS — hotfixes through June 2028. In exchange, you don't get anything shipped after it (Cypher 25, the VECTOR type, the new GQL syntax, ABAC, and so on).
  • Get on the train — new features and bug fixes every month. In exchange, skip a monthly upgrade and you're running an unsupported version.

For organizations with an "annual major upgrade" cadence, the fact that there's no third option is the crux of this model — and its most contentious part.

The cost of boarding the train is concrete too. Per the 5.26 → 2025.x upgrade guide, Java 21 becomes mandatory from 2025.01 (Java 17 support ends; Java 25 is supported starting 2025.10), cluster discovery service v1 is removed so the v2 migration must be completed before upgrading, and the Kafka/Spark connectors and the GraphQL library must be bumped to compatible patch versions as well.

Storage — After Block Format Became Default, Record Quietly Fades

Underneath the CalVer transition sits a storage-format generational change. Per the official store-formats doc, here's where things stand.

  • block — the recommended format for Enterprise Edition, and the default when nothing else is configured. It inlines properties into the same block as nodes and relationships to cut down pointer chasing, with data locality designed to serve queries off a handful of pages. Dense nodes overflow into a dense store based on a multi-root generational B+ tree.
  • aligned — Community Edition's default format. Block format doesn't exist in CE.
  • standard, high_limit — deprecated as of 5.23. The docs explicitly say not to use them for new databases.

The upgrade guide strongly recommends that 5.26 LTS users finish the block format migration before moving to 2025.x. There's one constraint on the migration: block format's token names (labels, property keys, relationship types) are capped at 16,383 characters — the maximum GQL identifier length — the first spot where a trace of the ISO standard is baked into the storage-format spec.

The direction is clearer in the changelogs. The 2025.10 changelog introduces VECTOR as "a new type supported by Cypher, the block store format, and the v6 drivers" — the new type system grows on the assumption of block format. On the other side, the legacy record format shows up in 2026 only as correction entries. The 2026 changelog fixed, in 2026.04, "a bug where relationship traversal could return incorrect results when nodes concurrently transition to dense in the record format," and in 2026.06, "a bug where undirected scans of multiple relationship types in the record format missed sibling relationships, undercounting output by about 50%." The fact that bugs at the level of returning wrong results are only now surfacing tells you where the center of gravity for testing and investment has shifted. If you're still sitting on the record format, these two entries make a fine paragraph of justification for a migration proposal.

The Language — Cypher Gets a Version Number

2025.06 (GA in July 2025) carried the most conceptual change of this era. The query language itself gained a version. The Cypher version-selection doc spells out the rule precisely.

  • Cypher 5 is frozen. Run with CYPHER 5 and you get "Cypher 5 as it existed at the 2025.06 release," and later language changes don't affect that query.
  • Cypher 25 keeps rolling. Run with CYPHER 25 and you get Cypher 25 as implemented by whatever Neo4j version is currently running. Cypher 25 is a language that grows with each monthly release.
CYPHER 25
MATCH (n:Order)-[r:SHIPPED_TO]->(:Address)
SET n = properties(r)

The version can be set as a database-wide default (db.query.default_language) as well as a query prefix, and procedures and functions (including APOC) are tied to the language version too — a procedure visible under Cypher 5 may be removed under Cypher 25 in the same APOC distribution. And per the 2026.02 changelog, the default language for new self-managed installs switched to CYPHER_25. Fresh installs now default to Cypher 25.

Anyone familiar with Rust editions or C++ standard switches will find this shape familiar. You need this mechanism to push the language toward the standard without breaking old queries. But there's an asymmetry hidden here — Cypher 25 exists only from 2025.06 onward, so teams staying on 5.26 LTS get neither Cypher 25 nor the GQL syntax layered on top of it. Choosing between the language's future and support stability is the actual shape of things right now.

GQL — How the Standard Lands in the Changelog

ISO/IEC 39075:2024, i.e., GQL, is a 610-page international standard published in April 2024 (currently at ISO stage 90.92, under revision review). The symbolic weight of being the first database language standard ISO has produced since SQL has been sufficiently discussed elsewhere, so here we just look at the actual landing — how does the standard make its way into a running engine?

Neo4j's approach isn't a "big-bang cutover" but planting GQL syntax into Cypher 25 a little at a time, every month. Laying the changelog out chronologically shows the trajectory.

  • 2025.06 — the FILTER clause (intermediate filtering), the LET clause (intermediate variable projection), the NEXT keyword for chaining query linear compositions, and brace-wrapped query blocks. All explicitly marked "GQL conformant." Cypher Shell's default error format also switched to GQLSTATUS-based gql.
  • 2026.02 — a batch of GQL-compatible function aliases added, including ceiling, local_time, zoned_datetime, collect_list, percentile_disc, stdev_pop (redirects to existing implementations, no behavior change).
  • 2026.04 — the FOR .. IN clause, GQL's alternative to UNWIND, and the IS LABELED label-check predicate.
  • 2026.05 — explicit path-mode support such as ACYCLIC for GPM shortest paths (ANY SHORTEST, SHORTEST k, etc.).
  • 2026.07 (not yet released as of writing, listed in the changelog) — the GROUP BY subclause for WITH and RETURN (noted as "introduced to align Cypher more closely with the GQL standard"), and the cardinality() function corresponding to GQL feature GF12.

Summarizing this as "Neo4j supports GQL" would be an overstatement. Neo4j itself has documented the precise state. The GQL conformance appendix is a declaration of minimum conformance per section 24.2 of the standard, and footnotes hang off the supported items — for instance, GQL's FLOAT and INTEGER have precision options, but Cypher's FLOAT is always a 64-bit double and INTEGER always 64-bit. And the same appendix carries a list of mandatory features still unsupported: GQL's session-management commands (SESSION SET, etc.), transaction commands (START TRANSACTION, COMMIT, ROLLBACK — in Neo4j the driver API fills that role instead), graph expressions like CURRENT_GRAPH, the schema-selection AT clause, and even mismatches in the reserved-word list.

Widening to the whole engine landscape doesn't change the conclusion much. Google Spanner Graph describes itself, in its own docs, as offering an "ISO GQL compatible graph query interface," while Memgraph's and FalkorDB's docs still put Cypher front and center. To summarize — GQL is real as a standard, but as of mid-2026, the portability promise of "write it in GQL and it runs anywhere" does not exist. Even the standard's mandatory features aren't all present in the flagship implementation, and vendor language ("conformant," "compatible") means different things from vendor to vendor. Choosing an engine because of GQL is premature, and it's honest to view GQL's present-day upside as roughly "the syntax you're newly learning happens to point in the standard's direction."

The Execution Engine — a Parallel Runtime, and a Scheduler That Prevents Deadlocks

Query execution kept moving over the same period too. Some background: Neo4j's parallel runtime is Enterprise-only and supports read queries only. It splits the pipeline into morsel-sized tasks divided among worker threads, and the notable feature is that scheduling is a per-worker distributed scheduler rather than a central queue. In 2026.05, the heuristic that planned variable-length patterns via the Repeat operator when input cardinality is 1 was switched to disabled by default — a place where, if you're on the parallel runtime, your execution plan may have quietly changed (it can be reverted via a query option).

On the write side, the notable arrival across 2026.05–2026.06 is transactional batch scheduling. When running CALL subqueries in parallel with IN CONCURRENT TRANSACTIONS (a staple pattern for bulk imports), the approach until now was detect-then-retry on deadlock. The new Cypher 25 syntax DISJOINT BY in 2026.06 instead takes a deadlock-prevention approach. It splits rows into batches based on an expression identifying which resources will be locked, running batches that share resources sequentially and batches that don't share resources concurrently.

DISJOINT BY (expr, ...)   -- explicitly declare the expression identifying lock resources
DISJOINT BY AUTO          -- infer lock expressions via static analysis of the subquery
DISJOINT BY NONE          -- explicitly disable batch scheduling

The changelog's own caveats are carried over here too — AUTO's static analysis only covers common patterns like MERGE backed by a uniqueness constraint and an index; if inference fails, execution proceeds with no constraint at all; and it only prevents deadlocks between batches from the same outer query, not deadlocks between separate concurrent queries. If you've been burned by deadlock-retry loops during bulk relationship creation, it's worth trying; if not, the default (disabled) is still the answer.

The same changelog also shows what life on the train looks like. 2026.02.1 fixed "potential data loss in MERGE when an ON MATCH expression depends on the variable being merged," and 2026.02.3 fixed an EXISTS subquery bug in the pipelined runtime, noting "a theoretical risk that incorrect data could have been written in the worst case, though no actual occurrence has been confirmed." Monthly releases mean these fixes arrive quickly — and also mean regressions needing fixes occur just as often. If you're on the train, reading patch notes has to be part of the monthly operational routine.

Horizontal Scaling — Infinigraph Property Sharding, a Separate Subscription

The "sharded property database" that keeps showing up throughout the changelogs is a distributed architecture called Infinigraph. The design is interesting: instead of partitioning the whole graph, it separates structure from properties. Node and relationship structure stays intact on a single "graph shard," while only properties are evenly distributed across multiple "property shards" via a hash function. The docs claim query semantics and ACID guarantees are preserved, and because graph traversal completes within the structure shard, the design avoids distributed-join hell.

Flip that around and the limits are just as clear — the structure itself still has to fit in one shard, so this scales for "graphs whose properties are heavy," not for "graphs whose structure outgrows one machine." And critically, as the docs state explicitly, this is a separate Infinigraph subscription product not included in standard Enterprise Edition (requires a sales inquiry). Engine development keeps showing up in the public changelog regardless — the 2026.07 changelog (unreleased) lists a batched index-seek operator for sharded deployments (RemoteNodeIndexSeek). That a feature exists and that you have access to it are two separate facts, and that's the state of play for this section.

Which Track to Stand On — A Decision Framework

To sum up, the choice splits like this.

If you stay on 5.26 LTS

  • Your upgrade windows are locked to quarterly or half-yearly cadences, and support contracts matter to your operations. Hotfixes run through June 2028 (5.26.28 shipped as recently as June 30, 2026).
  • That said, do the block format migration now — it's already 5.26's default anyway, and it's recommended as a prerequisite for a later move to CalVer.
  • Accept living without Cypher 25, the VECTOR type, the new GQL syntax, and ABAC.

If you get on the CalVer train

  • You have a pipeline that automates monthly (or at minimum bimonthly) upgrades, and an operational habit of reading patch notes.
  • Cypher 25's new syntax or vector features are a genuine requirement.
  • Your organization understands that the supported version is always "the single latest one."

If you're on Community Edition — it's more accurate to think of yourself as running a different product entirely, one with neither block format nor the parallel runtime (aligned format, single-threaded runtime). Most of this generation's engine-level improvements landed on the EE side.

If you're chasing GQL portability — that's still a direction, not a contract yet. As long as the flagship implementation's docs still carry a list of unsupported mandatory standard features, GQL guarantees no more than "learning syntax aligned with the standard's direction, in case you switch someday."

If you were looking for an embedded graph engine — that landscape shook hard last fall. Kùzu, the leading embedded option, had its repository archived as of October 10, 2025 (last release v0.11.3, repository), with community forks now carrying it forward. The rundown of options is already covered in the tools post, so refer there.

Closing

Compress a year and a half of Neo4j since the CalVer transition into one sentence and it's this — the engine grows monthly on top of block format, the language is moving version by version toward GQL, and the price of that speed is paid through an operational model where the supported version is always the single latest one. The standard (GQL) has been published, but portability hasn't arrived yet, and teams that want LTS and teams that want new features currently stand about as far apart as if they were on different major versions.

If you only ever touch graphs as raw material for RAG, most of this post is not immediately relevant — that's a layer hidden behind a managed service or an embedded store. But if you operate a graph DB directly, are choosing an engine right now, or have to evaluate the marketing phrase "supports the GQL standard," the material for that judgment is in the changelogs and conformance docs linked above, not a vendor slide deck. The process of a standard landing in an engine isn't flashy. Month by month, clause by clause, one batch of function aliases at a time — that's what it actually looks like.

References