Latest in branch 9.4
9.4.1
Released 12 May 2026
(1 day ago)
SoftwareElasticsearch
Branch9.4
Status
Supported
Initial release9.4.0
05 May 2026
(8 days ago)
Latest release9.4.1
12 May 2026
(1 day ago)
End of lifeTBD
(Supported)
Release noteshttps://www.elastic.co/docs/release-notes/elasticsearch
Source codehttps://github.com/elastic/elasticsearch/tree/9.4
Documentationhttps://www.elastic.co/docs/current/
Downloadhttps://www.elastic.co/downloads/elasticsearch
Elasticsearch 9.4 ReleasesView full list

What Is New in Elasticsearch 9.4

Elasticsearch 9.4 is a significant release centered on three themes: making ES|QL a first-class query engine (with Views, PromQL support, and time series commands), dramatically improving vector search throughput via the upgraded DiskBBQ algorithm, and reducing storage overhead for metrics workloads through synthetic IDs in TSDB. Below is a summary of the major change categories.

Category Highlights Impact
New Features ES|QL Views, PromQL source command, METRICS_INFO, TS_INFO, Prometheus remote write & query endpoints, synthetic IDs for TSDB High
Performance DiskBBQ 3x+ search improvement, counter rate 5x faster via tsid parallelism, Swiss Table hash for STATS, Top N parallelization High
Storage Synthetic IDs cut OTLP metrics storage up to 40%, binary doc values for wildcard/flattened fields, zstd 1.5.7 upgrade Medium-High
ES|QL Functions JSON_EXTRACT, MV_UNION, MV_INTERSECTS, USER_AGENT, REGISTERED_DOMAIN, URI_PART, ST_SIMPLIFY, ST_Buffer, LIMIT BY, MMR, sparkline Medium
Inference & ML FireworksAI embeddings and chat, Amazon Bedrock chat completion, Azure OpenAI OAuth2, multimodal inputs for all chat integrations, TEXT_EMBEDDING GA, RERANK GA Medium
Vector Search AVX-512 int8 kernels, bfloat16 scorers, native byte scorers, bbq_disk now default, configurable quantization bits (1/2/4/7) Medium-High
Bug Fixes SUM long overflow, ES|QL driver logging for 4xx, bloom filter thread-safety, AVX-512 MIP scoring, DiskBBQ off-heap size for empty indices Medium
Security Bouncycastle upgraded to 1.84, opaque random session IDs for ES|QL compute sessions, DLS/FLS blocked on views Medium

How Does ES|QL Views Change Query Architecture?

ES|QL 9.4 introduces Views -- virtual indices that wrap an ES|QL query and expose a stable set of columns. You reference a view exactly like a physical index inside a FROM clause, and you can mix views, indices, and wildcards in the same query. In practice, this lets you encapsulate complex pipelines (renames, type casts, derived fields, aggregations) behind a single name, so consumers never need to know the underlying index structure.

A single FROM can list several views at once; each view's pipeline runs independently before results are merged. Common transformations defined once in a view automatically apply everywhere -- dashboards, alerts, and ad-hoc queries all benefit without duplication.

-- Create a view that normalises a raw logs index
CREATE VIEW clean_logs AS
  FROM raw-logs-*
  | RENAME @timestamp AS ts, host.name AS host
  | EVAL level = UPPER(log.level)
  | WHERE level != "DEBUG";

-- Query it like any index
FROM clean_logs
| STATS count = COUNT(*) BY host
| SORT count DESC;

Security note: views cannot be queried when Document Level Security (DLS) or Field Level Security (FLS) is active on the underlying index. That boundary is enforced at the ES security layer, not the view definition.

What Does PromQL Support in ES|QL Actually Look Like?

The PROMQL source command is now available in ES|QL as a Tech Preview. It lets you write PromQL expressions directly inside an ES|QL pipeline, pulling data from Elasticsearch indices that store Prometheus-format metrics. This is not a thin proxy -- results flow into the ES|QL compute engine, so you can pipe them through SORT, LIMIT, WHERE, and any other ES|QL command.

PROMQL index=k8s-downsampled start="2026-02-17T08:00:00Z" end="2026-02-17T09:00:00Z" step=30m
  avg_bytes=(avg(rate(network.total_bytes_in[30m])))
| SORT avg_bytes DESC, step;

On the ingestion side, a new POST /_prometheus/api/v1/write endpoint accepts the standard Prometheus remote write binary protocol, so Elasticsearch can act as a drop-in Prometheus storage backend. Additional endpoints cover instant queries (/query), range queries (/query_range), series discovery (/series), and label enumeration (/labels) -- all returning standard Prometheus JSON formats.

This matters for teams already running Prometheus who want Elasticsearch's scalability and full-text capabilities without migrating all tooling at once. The Prometheus plugin is now enabled by default.

How Do the New Time Series Commands METRICS_INFO and TS_INFO Work?

METRICS_INFO and TS_INFO are two new introspection commands for ES|QL queries that start with a TS source. They give you schema-level visibility into your time series data before you commit to heavy aggregation queries.

METRICS_INFO returns one row per distinct metric, with columns including metric_name, data_stream, unit, metric_type, field_type, and dimension_fields. Use it to discover what metrics exist and how they are typed:

TS my_data_stream
| METRICS_INFO
| WHERE metric_type == "counter"
| SORT metric_name

TS_INFO goes one level deeper -- one row per metric-and-time-series combination. It adds a dimensions column containing a JSON object of dimension key-value pairs, which is useful for validating which labels actually apply to each series before building dashboards.

TS my_data_stream
| TS_INFO
| SORT metric_name, dimensions

What Storage Gains Come from Synthetic IDs in TSDB?

TSDB indices in time-series mode now use synthetic IDs instead of indexing the _id field. The real-world outcome is up to 40% storage reduction for OTLP metrics workloads and lower CPU overhead during segment merging, because there is no longer an inverted index maintained for _id.

Duplicate detection at ingest time is handled by a Bloom filter -- lightweight and fast. Lookups that previously used _id are delegated to other indexed fields like timestamps or dimension fields. Query and retrieval behavior is preserved; the change is transparent to existing queries.

Pair this with the new sequence number disabling for new TSDB indices (index.soft_deletes.enabled: false behavior) and you get further write amplification reductions on metrics-heavy clusters. Both features are backwards compatible.

How Much Faster Is Vector Search in 9.4?

The DiskBBQ algorithm received a substantial upgrade. On restrictive prefilter scenarios, search performance improves 3x or more. The new format adds configurable quantization bit depths (1, 2, 4, and 7 bits), native SIMD code improvements, and a way to condition non-IID vectors via an expert API. bbq_disk (DiskBBQ) is now the default quantization mode for new indices.

Counter rate aggregations in ES|QL now partition work using tsid prefixes, aligning tsids to workers inside the compute engine. This produces dense, sequential access patterns per time series and avoids unnecessary copies during counter value decoding. The result is up to 5x faster rate query responses at scale.

For ARM and x86, native kernels got dedicated optimizations: AVX-512 int8 kernels with cascade unrolling, vdotq_s32 for int7u/int8 on ARM NEON, SVE functions for BBQ Int4, and new bfloat16-specific and byte-vector scorers. Zero-copy SIMD vector scoring is now also enabled on the frozen tier (searchable snapshots).

-- semantic_text now defaults to bfloat16 + bbq_disk
-- No mapping change needed; new indices pick this up automatically
PUT my-index
{
  "mappings": {
    "properties": {
      "content": { "type": "semantic_text" }
    }
  }
}

What New ES|QL Functions and Commands Ship in 9.4?

9.4 expands the ES|QL function library significantly. Here is a grouped overview of the additions:

String and URI Functions

  • USER_AGENT command -- parses a user-agent string into structured fields
  • REGISTERED_DOMAIN command -- extracts the registered domain from a hostname
  • URI_PART command -- extracts components (scheme, host, path, etc.) from a URI
  • JSON_EXTRACT -- zero-copy extraction of values from JSON strings by path

Multivalue and Aggregation Functions

  • MV_UNION -- merges multivalue fields from multiple rows
  • MV_INTERSECTS -- returns the intersection of multivalue fields
  • mv_difference -- computes the set difference of multivalue fields
  • sparkline -- aggregate function returning a compact histogram representation
  • MMR (Maximal Marginal Relevance) command for result diversification
  • LIMIT BY (Tech Preview) -- limits results per group, similar to SQL TOP n PARTITION BY

Geospatial Functions

  • ST_SIMPLIFY -- reduces vertex count of geometries using the Douglas-Peucker algorithm
  • ST_Buffer -- generates a buffer polygon around a geometry
  • ST_SimplifyPreserveTopology -- simplifies without creating invalid geometries
  • ST_Dimension, ST_GeometryType, ST_IsEmpty -- metadata introspection on geometry fields

Dense Vector Functions (now GA)

  • TEXT_EMBEDDING -- GA (was Tech Preview)
  • Dense vector functions broadly -- GA
  • RERANK command -- GA
  • MV_EXPAND -- GA
  • Arithmetic operations on dense_vector (scalar and vector versions)
  • dense_vector support in COALESCE, COUNT, PRESENT, ABSENT, SUM

Time Series Aggregation Improvements

Time series aggregations in ES|QL now support windows smaller than the time bucket and windows that are not an exact multiple of the bucket:

-- Window smaller than bucket (new in 9.4)
TS metrics | STATS AVG(RATE(requests, 5m)) BY TBUCKET(10m), host

-- Non-multiple window (new in 9.4)
TS metrics | STATS AVG(RATE(requests, 15m)) BY TBUCKET(10m), host

Previously only windows equal to or exact multiples of the time bucket were accepted. This flexibility matters when aligning Prometheus scrape intervals with TSDB bucket sizes.

What Changed in Inference and ML Integrations?

The Inference API in 9.4 gains several new provider integrations and capabilities. FireworksAI is now supported for both embeddings and chat completions. Amazon Bedrock adds chat completion support. Azure OpenAI gets OAuth2 authentication and custom header support. All chat completion integrations now accept multimodal inputs (text + image).

On the model configuration side, semantic_text now defaults to BFLOAT16 quantization and uses bbq_disk storage, switching the default inference model to jina-v5. The Update Inference Endpoint operation now runs a provider validation call before persisting changes, catching misconfigured endpoints earlier.

For anomaly detection, AD jobs now use exponential backoff retry when reopening during system-initiated node reassignments, reducing false failures during rolling restarts. The Clone API Key endpoint is new, allowing duplication of API keys with adjusted metadata -- a convenience for automation pipelines that create per-service keys.

What Downsampling and Counter Accuracy Fixes Should You Know About?

Prior to 9.4, both downsampling methods (aggregate and last_value) stored only the last counter value in the downsampled document. This was accurate enough for last_value but produced incorrect rate calculations for the aggregate method when counters reset (process restart, counter overflow).

In 9.4, the aggregate method now stores the first encountered value per downsampled document and appends auxiliary documents whenever a counter reset is detected. Rate calculations across downsampled data now account for those resets, producing accurate results. This change is backwards compatible; existing downsampled data is not affected.

Additionally, aggregate_metric_double fields now support non-native ES|QL aggregations like STD_DEV, using the average (computed from sum and value_count sub-fields) as the representative value for operations where individual sub-fields are not directly applicable.

FROM k8s-downsampled
| STATS
    max = max(network.eth0.tx),
    std_dev = STD_DEV(network.eth0.tx)
  BY pod
| SORT pod

Notable Bug Fixes in 9.4

Several long-standing bugs are resolved in this release. The most notable for production systems:

  • SUM long overflow -- SUM on long fields silently produced wrong results on overflow. Fixed.
  • Bloom filter thread safety -- a bloom filter instance was shared across threads in certain codec paths, causing data corruption under concurrent reads. Fixed with per-thread isolation.
  • AVX-512 MIP scoring -- a wrong mask in the fpclass instruction classified negative infinity incorrectly during Maximum Inner Product scoring. Fixed.
  • DiskBBQ off-heap size for empty indices -- querying an empty index with DiskBBQ threw an incorrect off-heap size error. Fixed.
  • ES|QL driver 4xx logging -- client errors and cancellations were previously logged at wrong severity levels. Now correctly logged.
  • TSDB synthetic ID after restart/relocation -- synthetic IDs were not correctly usable after shard relocation or node restart. Fixed.
  • terminate_after not honored with size=0 -- aggregation-only queries ignored terminate_after. Fixed.
  • Async search cleanup against aliases -- cleanup tasks were not running against alias-backed indices. Fixed.

FAQ

Can I use ES|QL Views with cross-cluster search in 9.4?
Yes, with caveats. 9.4 adds CCS Remote Views Detection, which identifies views defined on remote clusters. However, views that use DLS or FLS on the underlying index cannot be queried at all -- that restriction applies regardless of whether the query is local or cross-cluster. Test view resolution carefully in mixed-version CCS setups during rolling upgrades.

Is the PromQL support production-ready in 9.4?
No -- the PROMQL source command, all four Prometheus REST endpoints (/query, /query_range, /series, /labels), and Prometheus remote write are all marked Tech Preview. The APIs may change. The Prometheus plugin itself is enabled by default, but you should treat the endpoints as experimental until GA is announced. The underlying ES|QL compute engine running these queries is stable.

What do I need to change to get the 40% TSDB storage reduction from synthetic IDs?
New TSDB indices created after upgrading to 9.4 automatically use synthetic IDs -- no mapping change is needed. Existing indices are not retroactively converted. If you need the storage savings on existing data, you will need to reindex into a new TSDB index. The feature also disables sequence numbers on new TSDB indices by default, which further reduces write overhead but means you cannot use optimistic concurrency control (if_seq_no / if_primary_term) on those indices.

Does upgrading to bbq_disk as the default vector format require reindexing?
Only for new indices. Existing indices with explicit dense_vector mappings keep their current format until you reindex. semantic_text fields on new indices will default to bbq_disk with BFLOAT16 automatically. If you have latency-sensitive use cases where the quantization tradeoff is unacceptable, you can override the index type explicitly in the dense_vector mapping. The jina-v5 model change for semantic_text also only applies to new endpoints; existing configured inference endpoints are unchanged.

The time series window size restrictions on RATE and TBUCKET were lifted -- does that affect existing queries?
Existing queries that already used exact-multiple windows continue to work identically. The change is purely additive -- previously invalid window configurations (smaller than bucket, or non-multiple of bucket) now execute rather than returning a validation error. If you have monitoring that parses ES|QL validation errors to detect misconfigured queries, review that logic since some previously-rejected queries will now run.

Releases In Branch 9.4

VersionRelease date
9.4.112 May 2026
(1 day ago)
9.4.005 May 2026
(8 days ago)