v2026.2.0
Pre-release
Pre-release
What's Changed
☢️ Breaking changes
- ClassSchemaAnalyzer ignores annotation flags reverting to default (one-way ratchet) (#1199)
Schema analysis from annotated model classes is now symmetric: reverting a boolean-style annotation flag (e.g.nullable,unique,filterable) to its default now clears the corresponding schema setting on the next re-analysis, instead of silently leaving the previous value in place. Classes that relied on a manually-set flag surviving re-analysis after the annotation stopped declaring it must now declare that flag explicitly. - Histograms: add range source-attribute support and multi-histogram schema (#1161)
Reference histograms can now be built from range-typed attributes (e.g. price bands, capacity intervals) in addition to scalar numeric ones, and a single reference can define multiple histograms instead of just one. Existing single-histogram configurations using@Reference(bucketed = @Histogram(...))must be rewritten to the array form@Reference(bucketed = {@Histogram(...)}). - REST referenceSummary schema rejects
requirementsas object and omitsentityGroupFetch(#1160)
The RESTreferenceSummary(and per-reference variants likereferenceBrandSummary)requirementsfield is now an array of single-key containers —{"entityFetch": {...}},{"entityGroupFetch": {...}}— instead of a single object combining both keys, andentityGroupFetchis now accepted at all. Existing REST requests that sentrequirementsas one object withentityFetch/entityGroupFetchside by side must switch to the array form. - Price histogram for LOWEST_PRICE entities ignores inner-record granularity (#1159)
ThepriceHistogramextra result now reflects one data point per inner-record price (selected by price-list priority) for entities usingLOWEST_PRICEhandling, instead of collapsing each entity to a single representative price. Bucket counts and thresholds forLOWEST_PRICEcatalogs will shift after upgrade — storefronts with hard-coded bucket expectations should re-baseline. - Introduce HostSystemEvent on system CDC stream — fix external APIs missing catalog availability after auto-upgrade (#1151)
Fixes a bug where a catalog auto-upgraded during boot stayed invisible to GraphQL, REST, and the Lab UI until the server was restarted. Introduces a new, opt-inHostSystemEventcategory on the system CDC stream for host-local signals; existing subscribers that don't explicitly opt in see no change in behavior. - Enforce WAL-first discipline for engine state to prevent version/WAL drift (#1137)
Closes several internal paths where the engine's state version could advance without a matching WAL entry, which could permanently wedge the engine and require manual repair. Startup now validates the WAL/state invariant, recovers a single in-flight step automatically via forward replay, and fails loudly instead of continuing on unrecoverable drift. - More optimized data structures in indexes & more granular storage parts (#760)
Reworks core index storage (attribute, filter, sort, price and reference indexes) onto transactional B+ trees and moves to leaf/page-granular persistence, so a transaction persists only the part of an index that actually changed instead of rewriting it whole — reducing write costs on high-cardinality entities and storage-layer vacuuming pressure. - Compute "dynamic" set of attribute histogram for references (#8)
GraphQL'sHistogramtype becomes an interface implemented byBaseHistogram(a direct replacement); the REST OpenAPIHistogramschema is likewise replaced byBaseHistogram, which extends it; and the GraphQLattributeHistogramsextra-result field is removed, its functionality replaced by histogram statistics available directly on reference summaries.
🚀 Features
- Fork RoaringBitmap into a persistent, transactional data structure
evitaDB now maintains its own fork of RoaringBitmap (vendored asevita_roaring_bitmap), reworked so bitmaps are a persistent, copy-on-write data structure instead of requiring a full clone on every write. This lets bitmap-backed indexes participate in the same transactional, snapshot-isolated model as the rest of the storage layer. Landed under the broader index-rework effort in #760, but significant enough to call out on its own. - Granular transaction conflict resolution (#503)
Introduces a schema-declared, hierarchically inherited conflict-resolution model that can be tuned from entity-level down to a single attribute, price, or reference, instead of a single engine-wide entity-level policy — reducing false rollbacks on concurrent updates that touch the same entity but different, semantically independent data. - Cheap savepoint snapshots: eliminate the O(N²) per-entity rollback cliff (#1252)
Removes an O(N²) cost cliff in per-entity transaction rollback: savepoint snapshots of shared diff layers (unique-attribute, faceted-reference and price indexes) no longer grow with the number of entities already touched in the same transaction, so large batch transactions with per-entity rollback stay cheap regardless of batch size. - perf: reduce OffsetIndex compaction memory churn and page-cache impact (#1157)
Reduces the allocation churn generated by OffsetIndex compaction on large entity collections, cutting the G1 old-generation pauses (previously up to ~2s on large files) that could otherwise surface as request timeouts on concurrently running queries. - New
groupHavingfiltering constraint (#1088)
Adds agroupHavingfiltering constraint that lets a query filter entities by a reference whose group entity satisfies a given filter — previously there was no way to express this. - Support for getting full price range for variants of a single master product (#1086)
Adds agetPriceRangeForSale*family of methods toPricesContractthat returns the lowest and highest price alongside the selling price in a single call, covering all three inner-record-handling strategies (NONE,LOWEST_PRICE,SUM) — useful for rendering a price range across a master product's variants. - Add aggregated crc32 checksum to WAL log (#1062)
Adds a rolling CRC32 checksum after every WAL record covering all preceding records, so WAL corruption can be detected at the byte level; existing WAL files are automatically upgraded to the new format. - Coalesce GraphQL / REST schema refresh on catalog schema changes (#1153)
GraphQL and REST no longer rebuild their per-catalog schema on every individual engine mutation or transaction commit; the rebuild now fires only when the catalog schema version actually changes, removing redundant rebuild work during bulk schema definition and on every data-only commit. - Traffic recording: on-demand export of the disk ring buffer contents, plus bug-hunt & JMH performance hardening (#1282)
Adds an on-demand export of the traffic-recording disk ring buffer as a downloadable zip, triggered over the gRPC traffic-recording service, so recorded traffic can be pulled off a running instance and replayed or analyzed elsewhere without waiting for the buffer to roll over. - Performance: reuse memoised filter formula tree for hierarchy statistics instead of re-planning (#1141)
Speeds up hierarchy statistics computation by deriving each per-statistics-base filter from the already-planned main query formula tree instead of re-planning it from the constraint tree, reducing planning overhead on queries with several hierarchy statistics variants. - Add support for filtering greater / lesser / between for primaryKeys (#1085)
Adds greater-than / less-than / between filtering constraints for primary keys, alongside the existing equality-based ones. - Support also distance
0for specific queries (#499)
stopAt(distance(...))now accepts0, letting hierarchy traversal (children,parents,siblings,fromRoot,fromNode) stop right at the pivot node without expanding into its descendants — useful for rendering a breadcrumb or menu header alongsidestatistics(...)counts for the full subtree. - Introduce GroupConstraint and align single-variant Child handling between schema builder and resolver (#1147)
FixesgroupHaving's inner filter constraints so they correctly target the referenced group entity instead of being accidentally routed to the referenced entity itself, and resolves a case where thegroupHavingselector inside histogram statistics could be silently dropped from GraphQL/REST requests. - expose engine settings and capabilities via GetEngineSettings management RPC
Adds aGetEngineSettingsmanagement RPC that reports the engine-wide default conflict resolution plus which capabilities (time travel, change data capture, traffic recording, query cache) are enabled — unlikegetConfiguration, it carries no sensitive values and stays readable even when the engine runs in read-only mode. - Expose evitadb_build_info metric (version, commit, java_version) (#1146)
Exposes anevitadb_build_info{version, commit, java_version}Prometheus gauge so the running evitaDB version and build commit can be read directly off a metrics scrape, without querying the management endpoint or checking logs. - dedicated traffic-recorder metrics; opt MemoryNotAvailableException out of error monitoring
Adds a dedicated set of traffic-recorder Prometheus metrics (off-heap block usage, active sessions, disk-buffer occupancy, throughput counters) and stops counting the internalMemoryNotAvailableExceptioncontrol-flow signal as an engine error, so genuine engine faults are no longer diluted by benign traffic-sampling skips inio_evitadb_errors_total. - export configurable query labels as Prometheus dimensions
Querylabel()values can now be opted in as Prometheus dimensions on query metrics via a newexportedQueryLabelsobservability option; with nothing configured (the default) no dimension is added, so existing metric cardinality is unchanged. - Traffic recorder: attribute post-discard trailing records/close to the discard reason, not SAMPLING (#1314)
Fixes traffic-recorder telemetry so activity that arrives after a session was discarded for genuine resource pressure (MEMORY_SHORTAGE/SERIALIZATION_ERROR) is attributed to that reason instead of being folded into the benignSAMPLINGcounter, giving operators an accurate signal for capacity-related discards. - Introduce grouped configuration sub-records for EvitaClientConfiguration (#1094)
GroupsEvitaClientConfiguration's connection, TLS, and timeout settings into dedicatedClientConnectionOptions,ClientTlsOptions, andClientTimeoutOptionssub-records with their own builders. The previous flat TLS and timeout accessors/setters are deprecated for removal in 2026.3, whilehost(),port(),systemApiPort(), andclientId()remain available at the top level. - Replace release-drafter with Claude-generated enriched release notes (#1131)
- add a debug mode that denies the optional prefetch
🐛 Bug Fixes
- Release pipeline: transient Claude CLI install failure aborts release and skips Docker publish (#1291)
- gRPC MakeCatalogAlive / MakeCatalogAliveWithProgress fail with UNAUTHENTICATED — missing from session interceptor whitelist (#1283)
- filterGroupBy ignored by reference histogramStatistics path (wrong group returned) (#1246)
- Range-typed bucketed reference histogram rendered with point semantics (inflated overallCount, range not spanning buckets) (#1245)
- BigDecimalNumberRange value not normalized to schema indexedDecimalPlaces on index write (attributeBetween/histogram returns zero matches) (#1238)
- indexedDecimalPlaces annotation silently dropped for BigDecimalNumberRange attributes in ClassSchemaAnalyzer (#1236)
- MoreThanSingleResultException in ReevaluateExpressionExecutor when filter has multiple GroupHaving siblings (#1233)
- Null-coalesce (
??) precedence trap + unhelpful error in FilterBy@Expression(#1232) - Memory leak: old Catalog snapshots retained (124 instances / ~6.6 GB) — #557 regression + CDC/static anchors (#1220)
- Scheduler: multiple bugs in thread/queue handling (purge sizing, swallowed exceptions, type/counter inconsistencies) (#1206)
- Request
requestpool rejects under load: ForkJoinPool parallelism clamped to CPU count, maxThreadCount ignored (#1204) - WAL-rotation purge reads an already-deleted .catalog file → FileNotFoundException under heavy compaction (#1203)
- CDC ring-buffer cleanup throws NoSuchElementException on empty subscriber map (#1201)
- Long-running tests: OffsetIndex torn-read race returns spurious null + TransactionalReference test seeding bug (#1189)
- OffsetIndex.count(historicalVersion) undercounts when the queried version was never recorded as a PastMemory (#1162)
- Some REST examples stopped working due to ReferenceSummary changes (#1156)
- Incorrect behavior of the query with NOT container (#1025)
- Issues applying partial rollback in atomic entity mutation (#569)
- address PR #1290 review - Markdown JavaDoc and cache placeholder for absent index
- address PR review — lazy span names, tail-slot guard, cast removal
- attribute post-discard traffic to the real discard reason
- break the JFR registration deadlock between event class init and the metadata lock
- B+ tree dirty-scope validation registers probe keys, not node objects
- bump logback 1.5.32 -> 1.5.34
- bump netty-codec-* to 4.2.16.Final
- cannot make catalog alive using specific gRPC service call without session
- carve out granular conflict items from the coarse entity conflict scope
- correct B+ tree internal-node block-size confusion across all transactional trees
- correct Deprecated since= values to reflect actual deprecation release
- de-flake gRPC traffic-export test and harden recorder activation
- detect conflict-resolution changes in schema differsFrom comparison
- enforce the documented keep-alive ping/idle configuration contract
- exclude evita_long_running_tests from PGP/duplicate-class CI checks
- exempt session-less gRPC endpoints via service wildcard
- expose conflict-resolution schema mutations in GraphQL/REST mutation unions
- expose GROUP-typed constraints in REST/GraphQL reference filter schema
- guarantee stage-order listener firing in CommitProgressRecord
- guard gRPC SET_FROM_NOW re-arm against a disabled request timeout
- harden configurable query-label export per review
- harden the gRPC session cancellation cascade and CDC ordering
- harden traffic ring-buffer drain, span-lock fairness, and export bounds
- honor InputStream skip contract and pin UTF-8 for traffic export metadata
- isolate traffic-metrics JFR capture by unique catalog name
- keep the two index views in step and stop orphaning facet layers
- maintain reflected references correctly across LIVE/ARCHIVED scopes
- make a reduced price index prove it holds nothing live before it is discarded
- make reused-catalog query benchmarks actually run and report
- make RingBufferInputStream mark/reset explicitly unsupported
- make the AI PR review actually produce a review
- name TransactionalStateProducer in assertion messages that check it
- port RoaringBitmap #837 and fix two inherited reverse/clone defects
- prevent and diagnose overlapping-leaf-page corruption in warm-up paged index flushes
- prime locale-id sequence in GlobalUniqueIndex shell copy
- publish the offset index descriptor before expiring the read Kryo pool
- read the lazily initialized logger through its accessor in EvitaServer
- reclaim the on-disk footprint of dropped and emptied indexes
- remove sleep-based race in CheckpointCoordinatorTest
- repair four defects in the PGP key verification script
- repair reference removal and duplicate bookkeeping in reference builders
- replace CAS-based completionSequencer with a synchronized append
- replace dropped NOT branch with EmptyFormula in FormulaOptimizer
- report zero size for absent directory instead of failing
- resolve aged-out conflict recompute against the effective catalog schema
- resolve OPENAI_API_KEY from the environment in translation plugin config
- restore Lombok processor path and mock index generic arity
- restrict session concurrency guard to read-write sessions
- serialize JShell source parsing with evaluation in documentation tests
- skip vendored RoaringBitmap suite in doc CI workflow
- soft-fail the release-notes path so a transient blip can't skip release assets
- treat flushFrequencyInMillis as milliseconds in trunk incorporation
- wait for catalog init before parallel backup/restore load test
⛓ Dependencies upgrades
- armeria ... 1.36.0 → 1.40.0
- bouncyCastle ... 1.83 → 1.85
- grpc ... 1.78.0 → 1.83.0
- jackson ... 2.21.1 → 2.22.1
- jackson.annotations ... 2.21 → 2.22
- junit.jupiter ... 6.0.3 → 6.1.2
- logback ... 1.5.32 → 1.6.0
- lombok ... 1.18.42 → 1.18.46
- maven.toolchains ... 3.2.0 → 3.3.0
- micrometer ... 1.16.3 → 1.17.0
- mockito.junit ... 5.22.0 → 5.23.0
- okhttp ... 5.3.2 → 5.4.0
- opentelemetry ... 1.59.0 → 1.64.0
- opentelemetry.semconv ... 1.40.0 → 1.43.0
- prometheus ... 1.5.0 → 1.8.0
- roaringbitmap ... 1.6.12 → 1.6.18
- slf4j ... 2.0.17 → 2.0.18
- swagger ... 2.2.43 → 2.2.52
Full Changelog: v2026.1.20...v2026.2.0