[[release-highlights]]
== What's new in {minor-version}

coming::[{minor-version}]

Here are the highlights of what's new and improved in {es} {minor-version}!
ifeval::["{release-state}"!="unreleased"]
For detailed information about this release, see the <<es-release-notes>> and
<<breaking-changes>>.

// Add previous release to the list
Other versions:

{ref-bare}/8.15/release-highlights.html[8.15]
| {ref-bare}/8.14/release-highlights.html[8.14]
| {ref-bare}/8.13/release-highlights.html[8.13]
| {ref-bare}/8.12/release-highlights.html[8.12]
| {ref-bare}/8.11/release-highlights.html[8.11]
| {ref-bare}/8.10/release-highlights.html[8.10]
| {ref-bare}/8.9/release-highlights.html[8.9]
| {ref-bare}/8.8/release-highlights.html[8.8]
| {ref-bare}/8.7/release-highlights.html[8.7]
| {ref-bare}/8.6/release-highlights.html[8.6]
| {ref-bare}/8.5/release-highlights.html[8.5]
| {ref-bare}/8.4/release-highlights.html[8.4]
| {ref-bare}/8.3/release-highlights.html[8.3]
| {ref-bare}/8.2/release-highlights.html[8.2]
| {ref-bare}/8.1/release-highlights.html[8.1]
| {ref-bare}/8.0/release-highlights.html[8.0]

endif::[]

// tag::notable-highlights[]

[discrete]
[[esql_inlinestats]]
=== ESQL: INLINESTATS
This adds the `INLINESTATS` command to ESQL which performs a STATS and
then enriches the results into the output stream. So, this query:

[source,esql]
----
FROM test
| INLINESTATS m=MAX(a * b) BY b
| WHERE m == a * b
| SORT a DESC, b DESC
| LIMIT 3
----

Produces output like:

|  a  |  b  |   m   |
| --- | --- | ----- |
|  99 | 999 | 98901 |
|  99 | 998 | 98802 |
|  99 | 997 | 98703 |

{es-pull}109583[#109583]

[discrete]
[[always_allow_rebalancing_by_default]]
=== Always allow rebalancing by default
In earlier versions of {es} the `cluster.routing.allocation.allow_rebalance` setting defaults to
`indices_all_active` which blocks all rebalancing moves while the cluster is in `yellow` or `red` health. This was
appropriate for the legacy allocator which might do too many rebalancing moves otherwise. Today's allocator has
better support for rebalancing a cluster that is not in `green` health, and expects to be able to rebalance some
shards away from over-full nodes to avoid allocating shards to undesirable locations in the first place. From
version 8.16 `allow_rebalance` setting defaults to `always` unless the legacy allocator is explicitly enabled.

{es-pull}111015[#111015]

[discrete]
[[add_global_retention_in_data_stream_lifecycle]]
=== Add global retention in data stream lifecycle
Data stream lifecycle now supports configuring retention on a cluster level,
namely global retention. Global retention \nallows us to configure two different
retentions:

- `data_streams.lifecycle.retention.default` is applied to all data streams managed
by the data stream lifecycle that do not have retention defined on the data stream level.
- `data_streams.lifecycle.retention.max` is applied to all data streams managed by the
data stream lifecycle and it allows any data stream \ndata to be deleted after the `max_retention` has passed.

{es-pull}111972[#111972]

[discrete]
[[enable_zstandard_compression_for_indices_with_index_codec_set_to_best_compression]]
=== Enable ZStandard compression for indices with index.codec set to best_compression
Before DEFLATE compression was used to compress stored fields in indices with index.codec index setting set to
best_compression, with this change ZStandard is used as compression algorithm to stored fields for indices with
index.codec index setting set to best_compression. The usage ZStandard results in less storage usage with a
similar indexing throughput depending on what options are used. Experiments with indexing logs have shown that
ZStandard offers ~12% lower storage usage and a ~14% higher indexing throughput compared to DEFLATE.

{es-pull}112665[#112665]

[discrete]
[[8_x_remove_zstd_feature_flag_for_index_codec_best_compression]]
=== [8.x] Remove zstd feature flag for index codec best compression
Backports the following commits to 8.x:  - Remove zstd feature flag for
index codec best compression. (#112665)

{es-pull}112857[#112857]

// end::notable-highlights[]


[discrete]
[[esql_multi_value_fields_supported_in_geospatial_predicates]]
=== ESQL: Multi-value fields supported in Geospatial predicates
Supporting multi-value fields in `WHERE` predicates is a challenge due to not knowing whether `ALL` or `ANY`
of the values in the field should pass the predicate.
For example, should the field `age:[10,30]` pass the predicate `WHERE age>20` or not?
This ambiguity does not exist with the spatial predicates
`ST_INTERSECTS` and `ST_DISJOINT`, because the choice between `ANY` or `ALL`
is implied by the predicate itself.
Consider a predicate checking a field named `location` against a test geometry named `shape`:

* `ST_INTERSECTS(field, shape)` - true if `ANY` value can intersect the shape
* `ST_DISJOINT(field, shape)` - true only if `ALL` values are disjoint from the shape

This works even if the shape argument is itself a complex or compound geometry.

Similar logic exists for `ST_CONTAINS` and `ST_WITHIN` predicates, but these are not as easily solved
with `ANY` or `ALL`, because a collection of geometries contains another collection if each of the contained
geometries is within at least one of the containing geometries. Evaluating this requires that the multi-value
field is first combined into a single geometry before performing the predicate check.

* `ST_CONTAINS(field, shape)` - true if the combined geometry contains the shape
* `ST_WITHIN(field, shape)` - true if the combined geometry is within the shape

{es-pull}112063[#112063]

