title: RedisTimeSeries 1.10 release notes

title: Requirements

text:
RedisTimeSeries v1.10.20 requires:

- Minimum Redis compatibility version (database): 7.2
- Minimum Redis Enterprise Software version (cluster): 7.2.4

title: v1.10.20 (October 2025)

text:
This is a maintenance release for RedisTimeSeries 1.10.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Details:

Bug fixes:

- [#1776](https://github.com/redistimeseries/redistimeseries/pull/1776) Potential crash on `TS.RANGE` with `ALIGN +`, `AGGREGATION twa` and `EMPTY` (MOD-11620, MOD-10484).

Improvements:

- Added support for Rocky Linux 9 and RHEL9 ARM.

title: v1.10.17 (April 2025)

text:
This is a maintenance release for RedisTimeSeries 1.10.

Update urgency: `MODERATE`: Plan an upgrade of the server, but it's not urgent.

Details:

Bug fixes:
- [#1725](https://github.com/redistimeseries/redistimeseries/pull/1725) `TS.DEL` crashes on keys with compactions if the deletion removes the last compaction bucket (MOD-8936)
- [LibMR#58](https://github.com/RedisGears/LibMR/pull/58) Crash when a cluster contains both 1.8 and newer nodes (MOD-8976, MOD-9192)

Improvements:
- [#1712](https://github.com/redistimeseries/redistimeseries/pull/1712) Added support for Azure Linux 3 (MOD-9170)
- [#1736](https://github.com/redistimeseries/redistimeseries/pull/1736) (Redis Enterprise only) Cross-key commands are handled by a random shard rather than the first shard (MOD-9262, MOD-9314)

title: v1.10.16 (January 2025)

text:
This is a maintenance release for RedisTimeSeries 1.10.

Update urgency: `SECURITY`: There are security fixes in the release.

Details:

- **Security and privacy:**
  - [#1673](https://github.com/redistimeseries/redistimeseries/pull/1673) (CVE-2024-51480) `TS.QUERYINDEX`, `TS.MGET`, `TS.MRANGE`, `TS.MREVRANGE` - potential integer overflow leading to an out-of-bounds write (MOD-7548)

- Improvements:
  - [#1663](https://github.com/redistimeseries/redistimeseries/pull/1663) Added support for Ubuntu 22 and macOS 13 and 14

title: v1.10.12 (March 2024)

text:
This is a maintenance release for RedisTimeSeries 1.10.

Update urgency: `LOW`: No need to upgrade unless there are new features you want to use.

Details:

- Improvements:

  - [#1593](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1593) More detailed LibMR error messages

title: v1.10.11 (October 2023)

text:
This is a maintenance release for RedisTimeSeries 1.10.

Update urgency: `LOW`: No need to upgrade unless there are new features you want to use.

Details:

- Bug fixes:

  - [LibMR#51](https://github.com/RedisGears/LibMR/pull/51) Crash on SSL initialization failure (MOD-5647)
  - [#1538](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1538) Amazon Linux 2: crash on SSL initialization. We now use openssl11-devel instead of openssl-devel (MOD-6015)

title: v1.10.9 (October 2023)

text:
This is a maintenance release for RedisTimeSeries 1.10.

Update urgency: `LOW`: No need to upgrade unless there are new features you want to use.

Details:

- Improvements:

  - [#1516](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1516) Added support for CBL-Mariner 2
  - [#1514](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1514) Added support for Rocky Linux 9 and RHEL9

title: v1.10.6 (September 2023)

text:
This is a maintenance release for RedisTimeSeries 1.10.

Update urgency: `SECURITY`: There are security fixes in the release.

Details:

- Security and privacy:

  - [#1506](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1506) Don’t expose internal commands (MOD-5643)

title: v1.10 GA (v1.10.4) (July 2023)

text: This is the General Availability release of RedisTimeSeries 1.10.

title: Headlines

text: RedisTimeSeries 1.10 introduces support for RESP3, performance improvements, and bug fixes.

title: Details

text:
Bug fixes (since 1.10-RC3):

- [#1494](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1494) Potential crash when using an invalid argument value

- The version inside Redis will be 1.10.4 in semantic versioning. Since the version of a module in Redis is numeric, we could not add a GA flag.

- Minimal Redis version: 7.2


title: RedisTimeSeries 1.12 release notes

summary: RedisTimeSeries 1.12 adds a highly requested feature - insertion-filter for close samples.

page_type: content

title: Requirements

role: overview

text:
RedisTimeSeries v1.12.9 requires:

- Minimum Redis compatibility version (database): 7.4
- Minimum Redis Enterprise Software version (cluster): 7.8

title: v1.12.9 (October 2025)

role: content

text:
This is a maintenance release for RedisTimeSeries 1.12.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Details:

Bug fixes:

- [#1776](https://github.com/redistimeseries/redistimeseries/pull/1776) Potential crash on `TS.RANGE` with `ALIGN +`, `AGGREGATION twa` and `EMPTY` (MOD-11620, MOD-10484).

Improvements:

- Added support for Rocky Linux 9 and RHEL9 ARM.

title: v1.12.6 (April 2025)

text:
This is a maintenance release for RedisTimeSeries 1.12.

Update urgency: `MODERATE`: Plan an upgrade of the server, but it's not urgent.

Details:

Bug fixes:
- [#1725](https://github.com/redistimeseries/redistimeseries/pull/1725) `TS.DEL` crashes on keys with compactions if the deletion removes the last compaction bucket (MOD-8936)
- [LibMR#58](https://github.com/RedisGears/LibMR/pull/58) Crash when a cluster contains both 1.8 and newer nodes (MOD-8976, MOD-9192)

Improvements:
- [#1712](https://github.com/redistimeseries/redistimeseries/pull/1712) Added support for Azure Linux 3 (MOD-9170)
- [#1736](https://github.com/redistimeseries/redistimeseries/pull/1736) (Redis Enterprise only) Cross-key commands are handled by a random shard rather than the first shard (MOD-9262, MOD-9314)

title: v1.12.5 (January 2025)

text:
This is a maintenance release for RedisTimeSeries 1.12.

Update urgency: `SECURITY`: There are security fixes in the release.

Details:

- **Security and privacy:**
  - [#1674](https://github.com/redistimeseries/redistimeseries/pull/1674) (CVE-2024-51480) `TS.QUERYINDEX`, `TS.MGET`, `TS.MRANGE`, `TS.MREVRANGE` - potential integer overflow leading to an out-of-bounds write (MOD-7548)

- Improvements:
  - [#1662](https://github.com/redistimeseries/redistimeseries/pull/1662) Added support for Ubuntu 22 and macOS 13 and 14

title: v1.12 GA (v1.12.2) (July 2024)

text: This is the General Availability release of RedisTimeSeries 1.12

title: Headlines

text: RedisTimeSeries 1.12 adds a highly requested feature: insertion-filter for close samples. Many sensors report data periodically. Often, the difference between the measured value and the previous measured value is negligible and related to random noise or to measurement accuracy limitations. When both the time difference and the value difference between the current and the previous sample are small, it may be preferable to ignore (not to add) the new measurement.

title: What's new in 1.12

text:
- [#1543](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1543) insertion-filter for close samples:

  - Two new [module configuration parameters](https://redis.io/docs/data-types/timeseries/configuration/) are introduced: `IGNORE_MAX_TIME_DIFF` and `IGNORE_MAX_VAL_DIFF`.
  - Two new similar per-key parameters are introduced: `ignoreMaxTimeDiff` and `ignoreMaxValDiff`.
  - `TS.ADD`, `TS.INCRBY`, and `TS.DECRBY` now have a new optional argument: `[IGNORE ignoreMaxTimeDiff ignoreMaxValDiff]`.
    When creating a new time series, these two values are used to set the per-key parameters and override the two module configuration parameters. These values are ignored when specified with an existing time series.
  - `[IGNORE ignoreMaxTimeDiff ignoreMaxValDiff]` is also supported by `TS.ALTER`.
  - For each call to `TS.ADD`, if the following conditions are met:
      - series is not a compaction
      - the series' `DUPLICATE_POLICY` is `LAST`
      - `timestamp` ≥ `max_timestamp`
      - `timestamp` - `max_timestamp` ≤ `ignoreMaxTimeDiff`
      - abs(`value` - `value_at_max_timestamp`) ≤ `ignoreMaxValDiff`))
    then this sample is ignored (not added) to the time series. `max_timestamp` is the maximal timestamp in the time series.
  - The same logic also applies for each call to `TS.MADD` based on the values of the per-key parameters.
  - When a sample is ignored, the returned value for `TS.ADD` and for the applicable array element in `TS.MADD` is `max_timestamp`.

title: Details

text:
- Bug fixes (since 1.12-RC1)

  - [#1607](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1607) Potential crash after deleting and recreating a source key of a compaction rule (MOD-7338)
  - [#1610](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1610) `COUNT` argument accepts non-positive values (MOD-5413)

- The version inside Redis will be 1.12.2 in semantic versioning. Since the version of a module in Redis is numeric, we could not add a GA flag.
- Minimal Redis version: 7.4


title: RedisTimeSeries 1.2 release notes

summary: Added compression. Stable ingestion time independent of the number of the data points on a time series. API performance improvements. Extended client support.

title: Requirements

text:
RedisTimeSeries v1.2.7 requires:

- Minimum Redis compatibility version (database): 5.0.0
- Minimum Redis Enterprise Software version (cluster): 6.0.12

title: v1.2.7 (June 2020)

text:
This is a maintenance release for version 1.2.

Details:

- Bugfixes:

    - #[414](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/414) Crash when a query had an empty label `(foo,)`

title: v1.2.6 (May 2020)

text:
This is a maintenance release for version 1.2.

Details:

- Minor enhancements:

    - #[403](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/403) Support for multi-value filtering in `TS.MGET` and `TS.MRANGE`.

- Bugfixes:

    - #[378](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/378) Using `snprintf` to ensure the same precision of floating-point value replies.
    - #[374](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/374) `TS.RANGE` crashed when COUNT argument was missing.
    - #[395](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/395) Check minimum compatible Redis version at module load time.

title: v1.2.5 (March 2020)

text:
Headlines:

- This release improves overall stability and provides fixes for issues found after the previous release.

Details:

- Bugfixes:
    - #[358](https://github.com/redistimeseries/redistimeseries/issues/358) [Wrong behaviour](https://groups.google.com/forum/?utm_medium=email&utm_source=footer#!topic/redistimeseries/wH0R69e8lOs) in `TS.RANGE` due to shifting left.
    - #[353](https://github.com/redistimeseries/redistimeseries/issues/353) Crash where the name of a time-series was already taken due to auto-compaction.

title: v1.2.3 (February 2020)

text:
Headlines:

- This release improves overall stability and provides fixes for issues found after the previous release.

Details:

- Bugfixes:
    - #[338](https://github.com/redistimeseries/redistimeseries/issues/338) reverting #[319](https://github.com/redistimeseries/redistimeseries/issues/319).  Aggregation should happen on deterministic time buckets.

title: v1.2 GA (1.2.2 - January 2020)

text:
This is the general availability (GA) release of RedisTimeSeries 1.2 (1.2.2).

Headlines:

- Compression added which can reduce memory up to 98% and improve read performance up to 50%.
- Stable ingestion time independent of the number of the data points on a time-series.
- Reviewed API with performance improvements and removed ambiguity.
- Extended [client support]()

(we will blog about this release soon including performance improvements results and the link here)

Full details:

- Added functionality
    - #[261](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/261) Samples are compressed using `Double Delta compression` which results in cost savings and faster query times.
    - Based on the [Gorilla paper](https://www.vldb.org/pvldb/vol8/p1816-teller.pdf).
        - In theory, this can save space up to 98%. (2 bits per sample in stead of 128).
        - In practice, a memory reduction of 5-8x is common but depends on the use case.
    - Initial benchmarks show 94% memory savings and performance improvements in reads up to XX%.
    - `UNCOMPRESSED` option in `TS.CREATE`.

- API changes / Enhancements
    - #[241](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/241) Overwriting the last sample with the same timestamp is not allowed.
    - #[242](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/242) revised `TS.INCRBY/DECRBY`
    - Returns a timestamp.  The behaviour is now aligned with `TS.ADD`.
    - The `RESET` functionality was removed. `RESET` contradicted the rewriting of the last sample (#[241](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/241)).
    Alternatively, you can reconstruct similar behaviour by
        - `TS.ADD ts * 1` + `sum` aggregation
        - `TS.INCRBY ts 1` + `range` aggregation
    - #[317](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/317) Aligning response on empty series of `TS.GET` with `TS.RANGE`.
    - #[285](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/285) #[318](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/318) Changed default behaviour of `TS.MRANGE` and `TS.MGET` to no longer returns the labels of each time-series in order reduce network traffic. Optional `WITHLABELS` argument added.
    - #[319](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/319) `TS.RANGE` and `TS.MRANGE` aggregation starting from requested timestamp.

- Performance improvements
    - #[237](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/237) Downsampling after time window is closed vs. downsampling with each sample.
    - #[285](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/285) #[318](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/318) Optional `WITHLABELS` argument added.  This feature improves read performance drastically.

- Minor Enhancements
    - #[230](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/230) `TS.INFO` now includes `total samples`, `memory usage`,`first time stamp`, ...
    - #[230](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/230) `MEMORY` calculates series memory footprint.

- Bugfixes since 1.0.3
    - #[204](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/204) Module initialization params changed to 64 bits.
    - #[266](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/266) Memory leak in the aggregator context.
    - #[260](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/260) Better error messages.
    - #[259](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/259) #[257](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/257) #[219](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/219) Miscellaneous.
    - #[320](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/320) Delete the existing key prior to restoring it.
    - #[323](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/323) Empty first sample on aggregation.

The version inside Redis will be 10202 or 1.2.2 in semantic versioning.


title: RedisTimeSeries 1.4 release notes

summary: Added ability to backfill time series.

title: Requirements

text:
RedisTimeSeries v1.4.14 requires:

- Minimum Redis compatibility version (database): 5.0.0
- Minimum Redis Enterprise Software version (cluster): 6.0.12

title: v1.4.14 (February 2022)

text:
This is a maintenance release for RedisTimeSeries 1.4.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Bug fixes:

- [#891](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/891), [#892](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/892) Fixed memory leak in parseCreateArgs when parsing error occurs (MOD-1958)

title: v1.4.13 (November 2021)

text:
This is a maintenance release for RedisTimeSeries 1.4.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Bug fixes:

- [#881](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/881) Replicate only successful insertion of `TS.MADD`

title: v1.4.11 (November 2021)

text:
This is a maintenance release for RedisTimeSeries 1.4.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Bug fixes:

- [#862](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/862) Index dictionary should be freed on removing the last element

title: v1.4.10 (July 2021)

text:
This is a maintenance release for RedisTimeSeries 1.4.

Update urgency: `HIGH`: There is a critical bug that may affect a subset of users. Upgrade!

Bug fixes:

- [#760](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/760) Avoid closing the same key twice, causing server crash on [`RENAME`]() of other keys

title: v1.4.9 (May 2021)

text:
This is a maintenance release for version 1.4.

Update urgency: Medium

Headlines:

- This release improves overall stability and provides fixes for issues found after the previous release.

Bug fixes:

- #[#712](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/712) Missing keytype check on TS.INCRBY/DECRBY causes shards to crash
- #[#719](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/719) Support for renaming time series keys

title: v1.4.8 (March 2021)

text:
This is a maintenance release for version 1.4.

Headlines:

- This release improves overall stability and provides fixes for issues found after the previous release.

Bug fixes:

- [#612](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/612) Crash on `MGET`/`MRANGE`
- [#606](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/606) Memory leak when key loaded from RDB
- [#624](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/624) Uninitialised memory access on log

title: v1.4.7 (December 2020)

text:
This is a maintenance release for version 1.4.

Headlines:

- This release improves overall stability, and provides fixes for issues found after the previous release.

Bug fixes:

- [#581](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/581) Misaligned allocators usage might crash Redis.
- [#588](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/588) `ON_DUPLICATE` min/max rules not working for negative value.

title: v1.4.6 (November 2020)

text:
This is a maintenance release for version 1.4.

Headlines:

This release improves overall stability and provides fixes for issues found after the previous release.

Minor enhancements:

- [#565](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/565)
    duplicate policy: add `SUM` option: If a previous sample exists, add the new sample to it so that the updated value is equal to (previous + new).
    If no previous sample exists, set the updated value equal to the new value. (PR [#565](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/565)
- [#559](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/559)
    Compressed chunk will be be the default global option
- [#559](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/559)
    Added `chunkType` to `TS.INFO`

Bug fixes:

- [#528](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/528)
    Out of order insert might crash Redis if there's an update to an empty downsampled key
- [#561](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/561)
    `TS.MRANGE` command might crash if there's an expired key that was deleted in the result set

title: v1.4 GA (September 2020)

text:
This is the General Availability release for RedisTimeSeries 1.4.

Highlights:

**Ability to backfill time series!** You can now add samples to a time series where the time of the sample is older than the newest sample in the series. This enables:

- Adding out of order of samples to time series.
- Batch loading of historical samples into an existing series.
- Updating existing samples (for example for compliance reasons).

This has been the most requested feature for RedisTimeSeries. We look forward to your feedback so we can move to a general availability release soon.

Details:

- Added functionality:
    - [#254](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/254) TS.REVRANGE and TS.MREVRANGE commands allow for querying in descending order of Timestamps.
    - [#503](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/503) - RDB saves the whole chunk instead of individual samples giving a speed and space improvement when saving or loading an RDB file
    - [#502](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/502) - The ability to set, at creation time, the data section size of each chunk using flag `CHUNK_SIZE`. TS.INFO uses `chunkSize` instead of `maxSamplesPerChunk`.
    - [#437](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/437) Allow backfilling of samples and updating of existing samples
        - Works with [compressed](https://redislabs.com/blog/redistimeseries-version-1-2-is-here/) and uncompressed series.
        - This comes with a performance hit when a sample is written out-of-order. We will publish numbers once we are generally available, but are still considering optimisations.
    - [#521](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/521) `DUPLICATE_POLICY` allows to configure on module, series and sample level how to handle duplicate samples. A duplicate sample is a sample for which the series holds already a sample on the same timestamp. Note that the default behaviour is equal to v1.2: `BLOCK`

Notes:
The version inside Redis will be 10405 or 1.4.5 in semantic versioning. Since the version of a module in Redis is numeric, we could not add an GA flag.


title: RedisTimeSeries 1.6 release notes

summary: Added support for aggregating across multiple time series (multi-key). Can compute queries such as "the maximum observed value of a set of time series" server-side instead of client-side.

title: Requirements

text:
RedisTimeSeries v1.6.19 requires:

- Minimum Redis compatibility version (database): 6.0.16
- Minimum Redis Enterprise Software version (cluster): 6.2.8

title: v1.6.19 (February 2023)

text:
This is a maintenance release for RedisTimeSeries 1.6.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Details:

- Bug fixes:

    - [#1397](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1397) Memory leak when trying to create an already existing key (MOD-4724, RED-93418)

title: v1.6.17 (July 2022)

text:
This is a maintenance release for RedisTimeSeries 1.6.

Update urgency: `HIGH`: There is a critical bug that may affect a subset of users. Upgrade!

Details:

- Bug fixes:

    - [#1240](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1240) Compaction rules are not saved to [RoF](https://docs.redis.com/latest/rs/databases/redis-on-flash) (Redis Enterprise)

title: v1.6.16 (June 2022)

text:
This is a maintenance release for RedisTimeSeries 1.6.

Update urgency: `HIGH`: There is a critical bug that may affect a subset of users. Upgrade!

Details:

- Features:

    - [#1193](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1193) Commands that don’t execute on the main thread now appear in [SLOWLOG]()

- Bug fixes:

    - [#1203](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1203) Compaction rules are not replicated (Replica Of) on Redis Enterprise
    - [#1204](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1204) When the last sample is deleted with [`TS.DEL`](), it may still be accessible with [`TS.GET`]()
    - [#1226](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1226) [`TS.MRANGE`](), [`TS.MREVRANGE`](): on a multi-shard environment, some chunks may be skipped

New RDB version (v5). RDB files created with 1.6.16 are not backward compatible.

title: v1.6.13 (June 2022)

text:
This is a maintenance release for RedisTimeSeries 1.6.

Update urgency: `HIGH`: There is a critical bug that may affect a subset of users. Upgrade!

Details:

- Bug fixes:

    - [#1176](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1176), [#1187](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1187) When executing [`DEL`](), chunk index could be set to a wrong value and cause some data to be inaccessible
    - [#1180](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1180) When executing [`MADD`](), make sure that only successful insertions are replicated

title: v1.6.11 (May 2022)

text:
This is a maintenance release for RedisTimeSeries 1.6.

Update urgency: `HIGH`: There is a critical bug that may affect a subset of users. Upgrade!

Details:

- Bug fixes:

    - [#1166](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1166) Stop forwarding multi-shard commands during cluster resharding and upgrade (MOD-3154)
    - [#1165](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1165) Stop forwarding multi-shard commands during transactions (`MULTI EXEC`) (MOD-3182)
    - [LibMR](https://github.com/RedisGears/LibMR): Fixed crash on multi-shard commands in some rare scenarios (MOD-3182)

title: v1.6.10 (May 2022)

text:
This is a maintenance release for RedisTimeSeries 1.6.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Details:

- Bug fixes:

    - [#1074](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1074) [`RANGE`](), [`REVRANGE`](), [`MRANGE`](), and [`MREVRANGE`](): Possibly incorrect result when using `ALIGN` and aggregating a bucket with a timestamp close to 0
    - [#1094](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1094) [LibMR](https://github.com/RedisGears/LibMR): Potential memory leak; memory release delay
    - [#1127](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1127) Memory leak on [`RANGE`]() and [`REVRANGE`]() when argument parsing fails
    - [#1096](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1096) [`RANGE`](), [`REVRANGE`](), [`MRANGE`](), and [`MREVRANGE`](): Using `FILTER_BY_TS` without specifying timestamps now returns an error as expected

title: v1.6.9 (February 2022)

text:
This is a maintenance release for RedisTimeSeries 1.6.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Details:

- Security and privacy:

    - [#1061](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1061) Internode communications encryption: support passphrases for PEM files

- Bug fixes:

    - [#1056](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1056) Return an error when a shard is down (in v1.6.8, returned an empty result)

title: v1.6 GA (v1.6.8) (January 2022)

text: This is the General Availability release of RedisTimeSeries 1.6.

title: Highlights

text: RedisTimeSeries 1.6 adds support for aggregating across multiple time series (multi-key). Before this version, queries such as "the maximum observed value of a set of time series" needed to be calculated client-side. Such queries can now be computed server-side, leveraging the heart of RedisGears ([LibMR](https://github.com/RedisGears/LibMR)) for clustered databases.

title: What's new in 1.6

text:
- Introduction of `GROUPBY` and `REDUCE` in `TS.MRANGE` and `TS.MREVRANGE` to add support for "multi-key aggregation" and support for such aggregations spanning multiple shards, leveraging [LibMR](https://github.com/RedisGears/LibMR). Currently, we support `min`, `max`, and `sum` as reducers and grouping by a label.

- [#722](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/722), [#275](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/275) Filter results using `FILTER_BY_TS` by providing a list of timestamps and `FILTER_BY_VALUE` by providing a `min` and a `max` value (`TS.RANGE`, `TS.REVRANGE`, `TS.MRANGE`, and `TS.MREVRANGE`).

- [#603](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/603), [#611](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/611), [#841](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/841) Introduction of TS.DEL which allows deleting samples in a time series within two timestamps (inclusive).

- [#762](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/762) Limit the number of returned labels in the response of read commands (`TS.MRANGE`, `TS.MREVRANGE`, and `TS.MGET`) using `SELECTED_LABELS`. This can be a significant performance improvement when returning a large number of series.

- [#655](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/655), [#801](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/801) Ability to align the aggregation buckets with the requested start, end, or specific timestamp on aggregation queries using `ALIGN` (`TS.RANGE`, `TS.REVRANGE`, `TS.MRANGE`, and `TS.MREVRANGE`).

- [#675](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/675) Add keyspace notifications for all CRUD commands. Check out [this test](https://github.com/RedisTimeSeries/RedisTimeSeries/blob/master/tests/flow/test_ts_keyspace.py) for the details.

- [#882](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/882) [Auto Tiering ](https://docs.redis.com/latest/rs/databases/redis-on-flash//#:~:text=Redis%20on%20Flash%20%20offers,dedicated%20flash%20memory%20(SSD).) support.


title: RedisTimeSeries 1.8 release notes

summary: Added a time-weighted average aggregator, gap filling, ability to control bucket timestamps, ability to control alignment for compaction rules, new reducer types, and ability to include the latest (possibly partial) raw bucket samples when retrieving compactions

title: Requirements

text:
RedisTimeSeries v1.8.19 requires:

- Minimum Redis compatibility version (database): 6.0.16
- Minimum Redis Enterprise Software version (cluster): 6.2.8

title: v1.8.19 (October 2025)

text:
This is a maintenance release for RedisTimeSeries 1.8.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Details:

Bug fixes:

- [#1776](https://github.com/redistimeseries/redistimeseries/pull/1776) Potential crash on `TS.RANGE` with `ALIGN +`, `AGGREGATION twa` and `EMPTY` (MOD-11620, MOD-10484).

Improvements:

- Added support for Rocky Linux 9 and RHEL9 ARM.

title: v1.8.17 (April 2025)

text:
This is a maintenance release for RedisTimeSeries 1.8.

Update urgency: `MODERATE`: Plan an upgrade of the server, but it's not urgent.

Details:

*Bug fixes:
- [#1725](https://github.com/redistimeseries/redistimeseries/pull/1725) `TS.DEL` crashes on keys with compactions if the deletion removes the last compaction bucket (MOD-8936)
- [LibMR#58](https://github.com/RedisGears/LibMR/pull/58) Crash when a cluster contains both 1.8 and newer nodes (MOD-8976, MOD-9192)

Improvements:
- [#1712](https://github.com/redistimeseries/redistimeseries/pull/1712) Added support for Azure Linux 3 (MOD-9170)
- [#1736](https://github.com/redistimeseries/redistimeseries/pull/1736) (Redis Enterprise only) Cross-key commands are handled by a random shard rather than the first shard (MOD-9262, MOD-9314)

title: v1.8.16 (January 2025)

text:
This is a maintenance release for RedisTimeSeries 1.8.

Update urgency: `SECURITY`: There are security fixes in the release.

Details

- **Security and privacy:**
  - [#1672](https://github.com/redistimeseries/redistimeseries/pull/1672) (CVE-2024-51480) `TS.QUERYINDEX`, `TS.MGET`, `TS.MRANGE`, `TS.MREVRANGE` - potential integer overflow leading to an out-of-bounds write (MOD-7548)

- Improvements:
  - [#1664](https://github.com/redistimeseries/redistimeseries/pull/1664) Added support for Ubuntu 22 and macOS 13 and 14

title: v1.8.13 (March 2024)

text:
This is a maintenance release for RedisTimeSeries 1.8.

Update urgency: `LOW`: No need to upgrade unless there are new features you want to use.

title: Details

text:
- Bug fixes:

  - [LibMR#51](https://github.com/RedisGears/LibMR/pull/51) Crash on SSL initialization failure (MOD-5647)

- Improvements:

  - [#1593](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1593) More detailed LibMR error messages

title: v1.8.12 (December 2023)

text:
This is a maintenance release for RedisTimeSeries 1.8.

Update urgency: `SECURITY`: There are security fixes in the release.

Details:

- Security and privacy:

  - [#1506](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1506) Don’t expose internal commands (MOD-5643)

- Bug fixes:

  - [#1494](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1494) Potential crash when using an invalid argument value

- Improvements:

  - [#1516](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1516) Added support for CBL-Mariner 2

title: v1.8.11 (July 2023)

text:
This is a maintenance release for RedisTimeSeries 1.8.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Details:

- Bug fixes:

    - [#1486](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1486) When using `LATEST`, results may contain samples earlier than `fromTimestamp` (`TS.RANGE`, `TS.REVRANGE`, `TS.MRANGE`, and `TS.MREVRANGE`)
    - [#1471](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1471) Potential crash on `TS.MRANGE` when aggregating millions of time series
    - [#1469](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1469) Potential memory leak in `TS.MRANGE` after eviction

- Performance enhancements:

    - [#1476](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1476) Significant performance improvement when using multiple label filters (`TS.MGET`, `TS.MRANGE`, `TS.MREVRANGE`, and `TS.QUERYINDEX`) (MOD-5338)

title: v1.8.10 (April 2023)

text:
This is a maintenance release for RedisTimeSeries 1.8.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Details:

- Bug fixes:

    - [#1455](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1455) `TS.ADD` - optional arguments are not replicated (MOD-5110)

title: v1.8.9 (March 2023)

text:
This is a maintenance release for RedisTimeSeries 1.8.

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Details:

- Bug fixes:

    - [#1421](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1421) Potential crash after deleting from a time series with an `AVG` compaction (MOD-4972)
    - [#1422](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1422) Incorrectly return an error when deleting from a time series with a compaction and with no expiry

title: v1.8.8 (March 2023)

text:
This is a maintenance release for RedisTimeSeries 1.8

Update urgency: `MODERATE`: Program an upgrade of the server, but it's not urgent.

Details:

- Bug fixes:

    - [#1290](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1290) Potential crash when using `FILTER_BY_TS`
    - [#1397](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1397) Memory leak when trying to create an already existing key (MOD-4724, RED-93418)

title: v1.8.5 (January 2023)

text:
This is a maintenance release for RedisTimeSeries 1.8.

Update urgency: `HIGH`: There is a critical bug that may affect a subset of users. Upgrade!

Details:

- Bug fixes:

    - [#1388](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1388) Potential crash when upgrading from v1.6 to 1.8 if there are compactions with `min` or `max` aggregation (MOD-4695)

title: v1.8.4 (December 2022)

text:
This is a maintenance release for RedisTimeSeries 1.8.

Update urgency: `HIGH`: There is a critical bug that may affect a subset of users. Upgrade!

Details:

- Bug fixes:

    - [#1360](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1360) Potential crash when upgrading from v1.6 to 1.8 if there are compactions with `min` or `max` aggregation (MOD-4559)
    - [#1370](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1370) Potential crash when using [TS.REVRANGE]() or [TS.MREVRANGE]() with aggregation
    - [#1347](https://github.com/RedisTimeSeries/RedisTimeSeries/pull/1347) When adding samples with [TS.ADD]() or [TS.MADD]() using  `*` as timestamp, the timestamp could differ between master and replica shards

- Improvements:
    - [#1215](https://github.com/RedisTimeSeries/RedisTimeSeries/issues/1215) OSS cluster: Support TLS and IPv6; introduce new configuration parameter: [OSS_GLOBAL_PASSWORD](configuration/#oss_global_password)

title: v1.8 GA (v1.8.3) (November 2022)

text: This is the General Availability release of RedisTimeSeries 1.8.

title: Highlights

text: RedisTimeSeries 1.8 introduces seven highly requested features, performance improvements, and bug fixes.

title: What's new in 1.8

text:
* **Optionally retrieving aggregation results for the latest (still open) bucket for compactions**

  Till version 1.8, when a time series is a compaction, [TS.GET](), [TS.MGET](), [TS.RANGE](), [TS.REVRANGE](), [TS.MRANGE](), [TS.MREVRANGE]() did not report the compacted value of the latest bucket. The reason is that the data in the latest bucket of a compaction is still partial. A bucket is ‘closed’ and compacted only upon the arrival of data that ‘opens’ a ‘new latest’ bucket.

  There are use cases, however, where the compaction of the latest bucket should be retrieved as well. For example, a user may want to receive the count of events since the start of the decade, and the retention period for raw data is only one month. Till version 1.8, the user would have to run two queries - one on a compaction and one on the latest raw data, and then sum the results. Since version 1.8, by specifying `LATEST`, it is possible to retrieve the latest (possibly partial) bucket as well.

  To report aggregations for the latest bucket, use the new optional `LATEST` flag to [TS.GET](), [TS.MGET](), [TS.RANGE](), [TS.REVRANGE](), [TS.MRANGE](), and [TS.REVRANGE]().

* **Optionally retrieving aggregation results for empty buckets**

  The commands [TS.RANGE](), [TS.REVRANGE](), [TS.MRANGE](), and [TS.MREVRANGE]() have an optional `[AGGREGATION aggregator bucketDuration]` parameter. When this parameter is specified, raw reports are aggregated per bucket.

  Till version 1.8, results were not reported for empty buckets. With `EMPTY`, it is now possible to report aggregations for empty buckets as well.

  The two primary reasons for wanting to retrieve values for empty buckets:

  - It is easier to align results from similar queries over multiple time series

  - It is easier to use the retrieved results with some external tools (e.g., charting tools)

  For the `sum` and `count` aggregators, the value 0 is reported for empty buckets.

  For the `min`, `max`, `range`, `avg`, `first`, `std.p`, and `std.s` aggregators, the value NaN (not a number) is reported.

  For the `last` aggregator and the new `twa` aggregator, the `EMPTY` flag is used for gap filling (see below).

  To report aggregations for empty buckets, use the new optional `EMPTY` flag in [TS.RANGE](), [TS.REVRANGE](), [TS.MRANGE](), and [TS.MREVRANGE]().

  Regardless of the values of `fromTimestamp` and `toTimestamp`, no data is reported for empty buckets that end before the earliest sample or begin after the latest sample in the time series.

* **A new aggregator: time-weighted average**

  When a time series holds discrete samples of a continuous signal (e.g., temperature), using `avg` to estimate the average value over a given timeframe would produce a good estimate only when the signal is sampled at constant intervals. If, however, samples are available at non-constant intervals (e.g., when some samples are missing), the `twa` aggregator produces a more accurate estimate by averaging samples over time instead of simply averaging the samples.

  This is an extreme example: the signal in the diagram above has 4 samples in its ‘high’ value and 13 samples in its ‘low’ value. However, the period in each of those states is about the same. It is easy to see that the simple average (avg) of all the 17 samples does not represent the signal’s average over time.

  Time-weighted average (`twa`) adds weight to each sample. The weight is proportional to the time interval that the sample represents. In the diagram, the time-weighted average over the whole period assigns appropriate weight to each sample, so the result represents the signal’s average value over the whole period much more accurately.

* **Gap filling: optionally interpolate or repeat last value for empty buckets**

  Gap filling is performed when using `EMPTY` together with either `last` or `twa` aggregator.

  Using `EMPTY` with the `twa` aggregator allows us to estimate the average of a continuous signal even for buckets where no samples were collected (gap-filling).

  Consider we want to use [TS.RANGE]() to calculate the average value of each bucket (p1, p2, p3 in the diagram above). Using avg, the value reported for bucket p2 would be NaN, as this bucket contains no samples. If we use `EMPTY` with `twa`, on the other hand, the average value for bucket p2 would be calculated based on the linear interpolation of the value left of p2 and the value right of p2.

  When sampling a continuous signal, we can use this ‘gap-filling’ capability to calculate the average value of the signal over equal-width buckets without concern about bucket alignment or missing samples.

  Using `EMPTY` with the last aggregator allows filling empty buckets by repeating the value of the previous sample. This is useful, for example, when values in the time series represent stock prices and the price has not been changed during a bucket’s timeframe.

* **Ability to control how bucket timestamps are reported**

  Till version 1.8, [TS.RANGE](), [TS.REVRANGE](), [TS.MRANGE](), and [TS.MREVRANGE]() returned the start time of each reported bucket as its timestamp.

  Changing this behavior and reporting each bucket’s start time, end time, or mid-time is now possible. This is required in many use cases. For example, when drawing bars in trading applications, annotating each bar with the end timestamp of the bucket it represents is very common.

  The way bucket timestamps are reported can be specified with the new optional `BUCKETTIMESTAMP` parameter of [TS.RANGE](), [TS.REVRANGE](), [TS.MRANGE](), and [TS.MREVRANGE]().

  `-` or `low`: the bucket's start time (default)

  `+` or `high`: the bucket's end time

  `~` or `mid`: the bucket's mid-time (rounded down if not an integer)

* **Ability to control alignment for compaction rules**

  Till version 1.8, compaction rules could not be aligned. One could specify a compaction rule with 24-hour buckets, and as a result, each bucket would aggregate events from midnight till the next midnight. The first bucket always started at the epoch and all other buckets were aligned accordingly.

  But what if we want to aggregate daily events from 06:00 to 06:00 the next day? We can now specify alignment for compaction rules.

  Alignment can be specified with the new optional `alignTimestamp` parameter of [TS.CREATERULE]() and the [COMPACTION_POLICY]() configuration parameter. Specifying `alignTimestamp` ensures that there is a bucket that starts exactly at `alignTimestamp` and all other buckets are aligned accordingly. `alignTimestamp` is expressed in milliseconds. The default value is 0 (aligned with the epoch).

* **New reducers**

  Till version 1.8, only the `sum`, `min`, and `max` could be used as reducer types.

  It is now possible, for example, to calculate the maximal temperature per timeframe for each sensor and then report the average temperature (avg reducer) over groups of sensors (grouped by a given label's value).

  This can be specified with the new reducer types ([TS.MRANGE]() and [TS.MREVRANGE](): `avg`, `range`, `count`, `std.p`, `std.s`, `var.p`, and `var.s`.

New RDB version (v7). RDB files created with v1.8.3 are not backward compatible.


title: Search and query commands

summary: Lists search and query commands and provides links to the command reference pages.

title: Content

text:
The following table lists search and query commands. See the command links for more information about each command's syntax, arguments, and examples.

| Command | Redis Software | Redis Cloud
Flexible & Annual | Redis Cloud
Free & Fixed | Description |
|:--------|:----------------------|:-----------------|:-----------------|:------|
| [FT.AGGREGATE]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Runs a search query on an index and groups, sorts, transforms, limits, and/or filters the results. |
| [FT.ALIASADD]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Adds an alias to an index.  |
| [FT.ALIASDEL]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Removes an alias from an index. |
| [FT.ALIASUPDATE]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Adds an alias to an index. If the alias already exists for a different index, it updates the alias to point to the specified index instead. |
| [FT.ALTER]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Adds a new field to an index. |
| [FT.CONFIG GET]() |  <nobr>❌ Not supported | <nobr>⚠ Not supported[2](#table-note-2) | <nobr>❌ Not supported</nobr> | Displays configuration options. |
| [FT.CONFIG HELP]() |   <nobr>❌ Not supported | <nobr>❌ Not supported | <nobr>❌ Not supported</nobr> | Describes configuration options. |
| [FT.CONFIG SET]() | <nobr>⚠ Not supported[1](#table-note-1) | <nobr>⚠ Not supported[2](#table-note-2) | <nobr>❌ Not supported</nobr> | Sets configuration options. |
| [FT.CREATE]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Creates an index. |
| [FT.CURSOR DEL]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Deletes a cursor. |
| [FT.CURSOR READ]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Reads the next results from an existing cursor. |
| [FT.DICTADD]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Adds terms to a dictionary. |
| [FT.DICTDEL]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Deletes terms from a dictionary. |
| [FT.DICTDUMP]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Returns all terms in the specified dictionary. |
| [FT.DROPINDEX]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Deletes an index. |
| [FT.EXPLAIN]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Returns the execution plan for a complex query as a string. |
| [FT.EXPLAINCLI]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Returns the execution plan for a complex query as an [array](). |
| [FT.HYBRID]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Performs hybrid search combining text search and vector similarity with configurable fusion methods. |
| [FT.INFO]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Returns index information and statistics.  |
| [FT._LIST]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Lists all indexes. |
| [FT.PROFILE]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Runs [FT.SEARCH]() or [FT.AGGREGATE]() and reports performance information. |
| [FT.SEARCH]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Searches an index for a text query and returns matching documents or document IDs. |
| [FT.SPELLCHECK]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Suggests spelling corrections for misspelled terms in a query. |
| [FT.SYNDUMP]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Returns a list of synonym terms and their synonym group IDs. |
| [FT.SYNUPDATE]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Creates or updates a synonym group with additional terms. |
| [FT.TAGVALS]() | ✅ Supported | ✅ Supported | ✅ Supported</nobr> | Returns all distinct values indexed in a tag field. |

1. Use [`rladmin`]() or the [REST API]() to change search and query configuration for Redis Software. See [search and query configuration compatibility with Redis Software]() for more information and examples.

2. [Contact support](https://redis.com/company/support/) to view the current configuration values or request configuration changes for Flexible or Annual Redis Cloud subscriptions.


title: Search and query configuration compatibility with Redis Software

summary: Search and query configuration settings supported by Redis Software and Redis Cloud.

title: Overview

text: To configure RediSearch in [Redis Software]() or [Redis Cloud](), use one of the following methods instead of [`FT.CONFIG SET`]().

title: Configure search in Redis Cloud

role: configuration

text:
For Redis Cloud:

- _Flexible or Annual [subscriptions]()_: contact [support](https://redis.com/company/support/) to request a configuration change.

- _Free or Fixed subscriptions_: you cannot change RediSearch configuration.

title: Configure search in Redis Software

text:
For Redis Software, use one of the following methods:

- Cluster Manager UI:

  1. From the **Databases** list, select the database, then click **Configuration**.

  1. Select the **Edit** button.

  1. In the **Capabilities** section, click **Parameters**.

  1. Enter the setting name and setting value in the **RediSearch** box.

      In the **Query Performance Factor** section, you can configure settings to improve query performance. See [Configure the query performance factor for Redis Search in Redis Software]() for more information.

  1. After you finish editing the module's configuration parameters, click **Done** to close the parameter editor.

  1. Click **Save**.

- [`rladmin tune db`]():

    [code example]

- [Configure module]() REST API request:

    [code example]

title: Configuration settings

text: See [configuration parameters]() in the Develop section for parameter details and compatibility with Redis Software and Redis Cloud.

code:
$ rladmin tune db db:<ID|name> module_name search \
        module_config_params "setting-name setting-value"

section_id: configure-search-in-redis-software

code:
POST /v1/modules/config/bdb/<ID>
    {
      "modules": [
        {
          "module_name": "search",
          "module_args": "setting-name setting-value"
        }
      ]
    }


title: Search and query

title: Search and query commands

summary: Configure the query performance factor for Redis Search in Redis Software to increase the performance of queries.

summary: Best practices for scalable Redis Search in Redis Software and Redis Cloud.

summary: Search and query Active-Active databases.

summary: Upgrade a database from Search 1.x to Search 2.x.

title: Upgrade a database to Search 2.x

title: Overview

text:
The [RediSearch 2.x module](https://redis.com/blog/introducing-redisearch-2-0/) is a source-available project that lets you build powerful search queries for open source Redis databases.
When combined with Redis Software, you can use the same protocols and [commands]()
to run geo-replicated queries and full-text searches over efficient in-memory indexes.

title: Index documents

text:
The search and query engine indexes documents, which are objects that represent data as field-value pairs. You can index more than one field per document, and these fields can represent text, numeric, or geospatial data types.

As the documents in your database change, the index automatically processes these changes to keep the search results up to date.

With indexes, you can do:
- Language-aware [fuzzy matching]()
- Fast [auto-complete]()
- [Exact phrase matching]()
- [Numeric filtering]()
- [Geo-radius queries]()

title: Supported document types

role: compatibility

text: You can store documents as Redis [hashes]() or [JSON](). To search and query JSON documents, you also need to enable [JSON]() in your database.

title: Hash documents

text:
With Redis [hashes](), each document is assigned to a single key and uses field-value pairs to represent the document's contents.

You can run [`HGETALL`]() to retrieve the entire hash document.

title: JSON documents

text:
You can index, search, and query JSON documents stored in your database.

For more information about how to search and query JSON documents, see the [quick start]().

title: Search features

text:
For full-text searches, you can customize the field queries and ranking of the search results.
When querying, you can use multiple predicates that query text, numeric, and geospatial fields in one query.
You can also sort by a specific field and limit the results with an offset to produce customized results pages.

Redis Open Source supports [over 15 natural languages]() for stemming and includes auto-complete engines with specific commands that can provide real-time [interactive search suggestions]().

text:
As a result of the new RediSearch architecture and methodology, [RediSearch 2.x supports Active-Active databases]().
You can now serve your index information from geo-distributed database instances.

title: Resharding indexed data

text:
By moving the index out of the keyspace and structuring the data as hashes, RediSearch 2.x makes it possible to reshard the database.
When half of the data moves to the new shard, the index related to that data is created synchronously and Redis removes the keys from the index when it detects that the keys were deleted.
Because the index on the new shard is created synchronously though, it's expected that the resharding process will take longer than resharding of a database without search and query enabled.

title: Limitations

role: limits

text: - You cannot use search and query capabilities with the [OSS Cluster API](). This limitation was fixed in Redis Software version 8.0.

title: More info

text:
- [Getting Started with RediSearch 2.0](https://redis.com/blog/getting-started-with-redisearch-2-0/)
- [Search and query quick start]()
- [Search and query configuration]()
- [Search and query commands]()
- [Search and query references]()
- [RediSearch source](https://github.com/RediSearch/RediSearch)


title: Configure the query performance factor for Redis Search in Redis Software

title: Overview

text:
Query performance factors are intended to increase the performance of queries, including [vector search](). When enabled, it allows you to increase a database's compute capacity and query throughput by allocating more virtual CPUs per shard. This is in addition to horizontal scaling with more shards which enables a higher throughput of key value operations. This document describes how to configure the query performance factor.

Some use cases might not scale effectively. Redis experts can help determine if vertical scaling with Redis Search will boost performance for your use case and guide you on whether to use vertical scaling, horizontal scaling, or both.

title: Prerequisites

text:
Redis Search requires a cluster running Redis Software version 7.4.2-54 or later. For the simplified configuration experience (no shard restart required, new UI, and new REST API), Redis Software version 8.x or later is required.

If you do not have a cluster that supports Redis Search, [install Redis Software]() version 7.4.2-54 or later on a new cluster, or [upgrade an existing cluster]().

title: Sizing

text:
1. Calculate the hardware requirements for your Redis database:

    1. Use the [hardware requirements documentation]() to derive the overall cluster architecture.

    1. Calculate the RAM requirements using the [Index Size Calculator](https://redis.io/redisearch-sizing-calculator/). The total RAM required is the sum of the dataset and index sizes.

1. [Determine the query performance factor](#calculate-query-performance-factor) you want and the required number of CPUs. Unused CPUs, above the 20% necessary for Redis, can be used for the scalable Redis Search.

1. Create a new Redis database with the number of CPUs configured for the query performance factor.

title: Calculate query performance factor

title: CPUs for query performance factor

text:
Vertical scaling of Redis Search is achieved by provisioning additional CPUs for the RediSearch module. At least 20% of the available CPUs must be reserved for Redis internal processing. Use the following formula to define the maximum number of CPUs that can be allocated to search.

| Variable | Value |
|----------|-------|
| CPUs per node | x |
| Redis internals | 20% |
| Available CPUs for Redis Search | floor(0.8 * x) |

title: Query performance factor versus CPUs

text:
The following table shows the number of CPUs required for each performance factor. This calculation is sensitive to how the search index and queries are defined. Certain scenarios might yield less throughput than the ratios in the following table.

| Scale factor | Minimum CPUs required for Redis Search <WORKERS> |
|----------------|-----------------------------------------|
| None (default) | 1 |
| 2 | 3 |
| 4 | 6 |
| 6 | 9 |
| 8 | 12 |
| 10 | 15 |
| 12 | 18 |
| 14 | 21 |
| 16 | 24 |

title: Example performance factor calculation

role: example

text:
| Variable | Value |
|----------|-------|
| CPUs per node | 8 |
| Available CPUs | floor(0.8 * 8)=6 |
| Scale factor | 4x |
| Minimum CPUs required for scale factor - WORKERS | 6 |

title: Configure query performance factor in the Cluster Manager UI

title: Redis Software 8.x and later {#config-db-ui-v8}

text:
Starting with Redis Software 8.x, configuring the query performance factor is simplified. You can select the query performance factor directly from the Cluster Manager UI without manually setting connection routing, connection limits, or module parameters. Changes to the query performance factor for existing databases take effect immediately without restarting shards.

To configure the query performance factor:

1. In the Cluster Manager UI, [create a new database]() or [edit an existing database]().

1. In the **Capabilities** section, click **Add parameters**.

1. In the **Parameters** dialog, use the **Query performance factor** dropdown to select the performance factor value (Standard, 2x, 4x, 6x, 8x, 10x, 12x, 14x, or 16x).

1. Click **Done** to close the parameter editor.

1. Click **Create** or **Save**.

The new configuration applies automatically. No shard restart is required, even for existing databases.

title: Prior to Redis Software 8 {#config-db-ui-prior}

text:
To manually configure the query performance factor in Redis Software versions prior to 8.x:

1. [Configure query performance factor parameters](#config-db-ui-params) when you create a new database or edit an existing database's configuration in the Cluster Manager UI.

1. If you configure the query performance factor for an existing database, you also need to [restart shards](#restart-shards). Newly created databases can skip this step.

#### Configure query performance factor parameters {#config-db-ui-params}

You can use the Cluster Manager UI to configure the query performance factor when you [create a new database]() or [edit an existing database]() with search enabled.

1. In the **Capabilities** section of the database configuration screen, click **Parameters**.

1. If you are creating a new database, select **Search and query**.

1. Adjust the **RediSearch** parameters to include:

    `WORKERS <NUMBER_OF_THREADS>`

    See [Calculate query performance factor](#calculate-query-performance-factor) to determine the minimum CPUs required to use for `<NUMBER_OF_THREADS>`.

1. Expand the **Query Performance Factor** section and enter the following values:

    - `mnp` for **Connections routing**

    - `32` for **Connections limit**

1. Click **Done** to close the parameter editor.

1. Click **Create** or **Save**.

#### Restart shards {#restart-shards}

After you update the query performance factor for an existing database, restart all shards to apply the new settings. You can migrate shards to restart them. Newly created databases can skip this step.

1. Use [`rladmin status shards db <db-name>`]() to list all shards for your database:

    [code example]

    Example output:

    [code example]

    Note the following fields for the next steps:
    - `ID`: the Redis shard's ID.
    - `NODE`: the node on which the shard currently resides.
    - `ROLE`: `master` is a primary shard; `slave` is a replica shard.

1. For each replica shard, use [`rladmin migrate shard`]() to move it to a different node and restart it:

    [code example]

1. After you migrate the replica shards, migrate the original primary shards.

1. Rerun `rladmin status shards db <db-name>` to verify the shards migrated to different nodes:

    [code example]

    Example output:

    [code example]

title: Configure query performance factor with the REST API

title: Redis Software 8.x and later {#rest-api-v8}

text:
Starting with Redis Software 8.x, you can configure the query performance factor using the [`query_performance_factor`]() object in the [BDB object](). You no longer need to manually set `sched_policy`, `conns`, or module `WORKERS` parameters. Changes take effect immediately without restarting shards.

#### Create a new database {#create-db-rest-api-v8}

To create a database with the query performance factor enabled, use the [create database REST API endpoint]() with the `query_performance_factor` field:

[code example]

The following [cURL](https://curl.se/docs/) request creates a new database from the JSON example:

[code example]

#### Update an existing database {#update-db-rest-api-v8}

To configure the query performance factor for an existing database, use the [update database configuration]() endpoint with the `query_performance_factor` field:

[code example]

No shard restart is required. The new configuration applies automatically.

#### Query performance factor object fields

| Field | Type/Value | Description |
|-------|------------|-------------|
| active | boolean (default: false) | If true, enables query performance factor for the database |
| scaling_factor | integer (range: 0-16) (default: 0) | Scales the magnitude of the query performance factor |

See the [`query_performance_factor` object reference]() for more details.

title: Prior to Redis Software 8 {#rest-api-prior}

text:
You can configure the query performance factor when you [create a new database](#create-db-rest-api) or [update an existing database](#update-db-rest-api) using the Redis Software [REST API]().

#### Create new database with the REST API {#create-db-rest-api}

To create a database and configure the query performance factor, use the [create database REST API endpoint]() with a [BDB object]() that includes the following parameters:

[code example]

See [Calculate performance factor](#calculate-query-performance-factor) to determine the value to use for `<NUMBER_OF_CPUS>`.

##### Example REST API request for a new database

The following JSON is an example request body used to create a new database with a 4x query performance factor configured:

[code example]

The following [cURL](https://curl.se/docs/) request creates a new database from the JSON example:

[code example]

#### Update existing database with the REST API {#update-db-rest-api}

To configure the query performance factor for an existing database, use the following REST API requests:

- [Update database configuration]() to modify the DMC proxy.

- [Upgrade module]() to set the search module’s query performance factor.

- Because this procedure also restarts the database shards, you should perform it during a maintenance period.
- This procedure overwrites any existing module configuration parameters.

The following example script uses both endpoints to configure a 4x query performance factor:

[code example]

title: Monitoring Redis Search

text:
To monitor a database with a query performance factor configured:

1. Integrate your Redis Software deployment with Prometheus. See [Prometheus and Grafana with Redis Software]() for instructions.

1. Monitor the `redis_process_cpu_usage_percent` shard metric.

    The following Prometheus UI screenshot shows `redis_process_cpu_usage_percent` spikes for a database with two shards:

    - 1st 100% spike: [`memtier_benchmark`](https://github.com/RedisLabs/memtier_benchmark) search test at the default (no additional CPUs for search).

    - 2nd 100% spike: reconfiguration and shard restart for a 4x query performance factor.

    - 3rd 600% spike: `memtier_benchmark` search test with threading at a 4x query performance factor (6 CPUs per shard).

code: rladmin status shards db db-name

code:
SHARDS:
    DB:ID   NAME                ID      NODE   ROLE   SLOTS   USED_MEMORY STATUS
    db:2    db-name             redis:1 node:1 master 0-16383 1.95MB      OK
    db:2    db-name             redis:2 node:2 slave  0-16383 1.95MB      OK

code: rladmin migrate shard <shard_id> target_node <node_id>

code:
SHARDS:
    DB:ID   NAME                ID      NODE   ROLE   SLOTS   USED_MEMORY STATUS
    db:2    db-name             redis:1 node:2 master 0-16383 1.95MB      OK
    db:2    db-name             redis:2 node:1 slave  0-16383 1.95MB      OK

scalable-search-db

type: redis

authentication_redis_pass: <your default db pwd>

proxy_policy: all-master-shards

shards_placement: sparse

module_name: search

code: curl -k -u "<user>:<password>" https://<host>:9443/v1/bdbs -H "Content-Type:application/json" -d @scalable-search-db.json

code:
curl -k -u "<user>:<password>" -X PUT https://<host>:9443/v1/bdbs/<DB_ID> -H "Content-Type:application/json" -d '{
    "query_performance_factor": {
        "active": true,
        "scaling_factor": 4
    }
}'

sched_policy: mnp

module_args: WORKERS <NUMBER_OF_THREADS>

module_args: WORKERS 6

code:
#!/bin/bash
export DB_ID=1
export CPU=6
export MODULE_ID=`curl -s -k -u "<user>:<password>" https://<host>:9443/v1/bdbs/$DB_ID | jq '.module_list[] | select(.module_name=="search").module_id' | tr -d '"'`

curl -o /dev/null -s -k -u "<user>:<password>" -X PUT https://<host>:9443/v1/bdbs/$DB_ID -H "Content-Type:application/json" -d '{
    "sched_policy": "mnp",
    "conns": 32
}'

sleep 1

curl -o /dev/null -s -k -u "<user>:<password>" https://<host>:9443/v1/bdbs/$DB_ID/modules/upgrade -H "Content-Type:application/json" -d '{
    "modules": [
      {
        "module_name": "search",
        "new_module_args": "WORKERS '$CPU'",
        "current_module": "'$MODULE_ID'",
        "new_module": "'$MODULE_ID'"
      }
    ]
}'


title: Upgrade a database to Search 2.x

title: Overview

text:
RediSearch 2.x includes some significant architectural changes that improve functionality.
The main change is that RediSearch 2.x stores indexes outside of the Redis database that contains the data.
This makes commands more efficient and improves replication between clusters because the index changes are managed by the participating clusters rather than being synchronized with the data.

This change allows databases with RediSearch to support:

- [Active-Active databases]()
- Database cluster re-sharding
- Replica Of to a sharded destination database
- [EXPIRE]() of documents reflected in the index

In addition, RediSearch 2.x indexes data that already existed in the database at the time that the index was created.

To upgrade a Redis Software database with RediSearch 1.x to RediSearch 2.x, you have to set up a new database with RediSearch 2.x and use the `RediSearch_Syncer.py` script to replicate the data from the old database into the new database.

After you create the database or after you replicate the data, [create an index]() with a prefix or filter that defines the keys that you want to index.

title: Prerequisites

text:
Install Python 3 on the host where you plan to run the synchronization script:

[code example]

title: Limitations

text:
- Suggestions (`FT.SUG` APIs) and spell check dictionaries are not replicated from the source database. You need to add them manually.
- If there are multiple indexes on the source and the documents do not have prefixes that identify them with an index, RediSearch 2.x can't index the documents in their respective indexes.
- The `NOSAVE` option is no longer supported. Indexes created with the `NOSAVE` option can't be upgraded.
- Databases that contain temporary indexes can't be upgraded.
- Any attempt to add, delete, or modify an index during the upgrade will cause the replication process to fail. During the upgrade, the source database can only receive `FT.ADD` and `FT.DEL` commands.

title: Replicate data from RediSearch 1.x to RediSearch 2.x

text:
To replicate a RediSearch 1.x database to a RediSearch 2.x database:

1. Sign in to the admin console of the Redis Software cluster where you want to host the new RediSearch 2.x database.

1. [Add the RediSearch 2.x module](#add-new-module) to the cluster.

1. [Create a new database](#create-db) with RediSearch 2.x.

1. [Migrate data](#migrate-data) to the RediSearch 2.x database.

title: Add RediSearch 2.x to the cluster {#add-new-module}

text:
1. Download the RediSearch 2.x module package from the [Redis Download Center](https://redis.io/downloads).

1. In the Redis Software admin console, select **settings**.

1. In **redis modules**, select the **Add module** button.

1. Use the file browser to select the module package and upload it to the cluster.

title: Create a RediSearch 2.x database {#create-db}

text:
1. [Create a database]() and configure its settings.

1. In the **Redis Modules** section:

    1. Select the **Add** button:

    1. Select **RediSearch 2** from the dropdown list.

    1. Select the **OK** button to confirm:

1. Select the **Activate** button to create the database.

title: Migrate data {#migrate-data}

text:
1. Download the RediSearch_Syncer package for your operating system:

    - [RedHat Enterprise Linux 7](http://redismodules.s3.amazonaws.com/redisearch/RediSearchSyncer/RediSearchSyncer-rhel7.zip)
    - [Ubuntu 18.04](http://redismodules.s3.amazonaws.com/redisearch/RediSearchSyncer/RediSearchSyncer-bionic.zip)
    - [Ubuntu 16.04](http://redismodules.s3.amazonaws.com/redisearch/RediSearchSyncer/RediSearchSyncer-xenial.zip)
    - [Ubuntu 14.04](http://redismodules.s3.amazonaws.com/redisearch/RediSearchSyncer/RediSearchSyncer-trusty.zip)

1. Extract the package:

    [code example]

1. In the extracted directory, run the RediSearch_Syncer.py script:

    [code example]

    Replace the following variables with your own values:

    - `destination url` - The replication URL of the RediSearch 2.x database. To find this value, go to the database configuration screen in the admin console and select **Get Replica of source URL**.

    - `source url` - The replication URL of the RediSearch 1.x database. To find this value, go to the database configuration screen in the admin console and select **Get Replica of source URL**.

    - `--add-prefix <prefix>` (optional) - Adds a prefix to all of the hashes that are replicated to the new database.

Only use the `add-prefix` option if you want to index all of the hashes in the same index in the source database.

    The script shows a table with the progress of the replication process.
    Press **F5** to see the updated status.

    For example:

    [code example]

1. Stop the processes that are sending requests to the source database so all of the data gets synchronized to the destination database.

1. Run `FT.INFO` on both source and destination databases and compare the number of indexed documents. The replication process is complete when the number of indexed documents is the same in both databases.

1. When the status field is `st_in_sync`, you can press **Ctrl-C** to cancel the synchronization process.

1. Press **Q** to quit the `RediSearch_Syncer.py`.

You can now redirect your database connections to the RediSearch 2.x database.

code: sudo apt install python3

section_id: prerequisites

code: unzip <package_name>

section_id: migrate-data-migrate-data

code: python3 RediSearch_Syncer.py -d <destination_url> -s <source_url> [--add-prefix <prefix>]


title: Best practices for scalable Redis Search

title: Overview

text: [Vertical scaling of Redis Search]() requires configuring query performance factors. With careful crafting of search indexes and queries, query performance factors allow throughput scaling up to 16X. The following recommendations can help optimize your indexes and queries to maximize the performance benefits from additional CPUs allocated by query performance factors.

title: Best candidates for query performance factor improvements

text:
- Query types:

    - [Full-text]()

    - [Tag]()

    - [Vector]()

    - [Numeric]()

    - [Geo]()

- Result set types:

    - Small result sets

    - Document subsets that are indexed in their [non-normalized]() form

title: Best practices

text:
If query performance factors have not boosted the performance of your queries as much as expected:

1. Verify your index includes all queried and returned fields.

1. Identify and avoid query [anti-patterns]() that limit scalability.

1. Follow best practices to [improve indexing](#improve-indexing).

1. Follow best practices to [improve queries](#improve-queries).

title: Improve indexing

text:
Follow these best practices for [indexing]():

- Include fields in the index definition that are used in the query or the required result sets (projections).

- Use `SORTABLE` for all fields returned in result sets.

- Use the `UNF` option for `TAG` and `GEO` fields.

- Use the `NOSTEM` option for `TEXT` fields.

title: Improve queries

text:
Follow these best practices to optimize [queries]():

- Specify the result set fields in the `RETURN` or `LOAD` clauses and include them in the index definition. Don’t just return the default result set from [`FT.SEARCH`]()  or `LOAD *` from [`FT.AGGREGATE`]().

- Use `LIMIT` to reduce the result set size.

- Use [`DIALECT 3`]() or higher for any queries against JSON.

title: Index and query examples

text: The following examples depict an anti-pattern index schema and query, followed by a corrected schema and query, which allows for scalability with Redis Search.

title: Anti-pattern index schema

text:
The following index schema is not optimized for vertical scaling:

[code example]

title: Anti-pattern query

text:
The following query is not optimized for vertical scaling:

[code example]

title: Improved index schema

text:
Here's an improved index schema that follows best practices for vertical scaling:

[code example]

title: Improved query

text:
Here's an improved query that follows best practices for vertical scaling:

[code example]

title: Performance results

role: performance

text: The following benchmarks show the performance improvements for different query types achieved with query performance factors. Vector, tag, and text queries strongly benefit, while numeric and geographic queries show more limited improvements.

title: Vector schema type

text:
#### Vector ingest

| Shards | Threads per shard | CPUs | Speedup factor |
|--------|-------------------|------|----------------|
| 1      | 0                 | 1    | 0              |
| 6      | 0                 | 6    | 6.6            |
| 1      | 6                 | 6    | 2.5            |
| 2      | 6                 | 12   | 6.1            |
| 4      | 6                 | 24   | 24.3           |

#### Vector query

| Shards | Threads per shard | CPUs | Speedup factor |
|--------|-------------------|------|----------------|
| 1      | 0                 | 1    | 0              |
| 6      | 0                 | 6    | 0.8            |
| 1      | 6                 | 6    | 4.7            |
| 2      | 6                 | 12   | 5.1            |
| 4      | 6                 | 24   | 5.6            |

title: Tag schema type

text:
| Worker threads | % change |
|----------------|----------|
| 0              | 0        |
| 6              | 135.88   |

title: Text schema type

text:
#### Two-word union queries

| Worker threads | Queries per second | % change |
|----------------|--------------------|----------|
| 0              | 188                | 0        |
| 6              | 1,072              | 470      |
| 12             | 1,995              | 961      |
| 18             | 2,834              | 1,407    |

#### Two-word intersection queries

| Worker threads | Queries per second | % change |
|----------------|--------------------|----------|
| 0              | 2,373              | 0        |
| 6              | 12,396             | 422      |
| 12             | 17,506             | 638      |
| 18             | 19,764             | 733      |

#### Simple one-word match

| Worker threads | Queries per second | % change |
|----------------|--------------------|----------|
| 0              | 476                | 0        |
| 6              | 2,837              | 496      |
| 12             | 5,292              | 1,012    |
| 18             | 7,512              | 1,478    |

title: Numeric schema type

text:
| Worker threads | Queries per second | % change |
|----------------|--------------------|----------|
| 0              | 33,584             | 0        |
| 1              | 36,993             | 10.15    |
| 3              | 36,504             | 8.69     |
| 6              | 36,897             | 9.86     |

title: Geo schema type

text:
#### Geo queries without UNF

| Worker threads | Queries per second | % change |
|----------------|--------------------|----------|
| 0              | 48                 | 0        |
| 6              | 96                 | 100      |
| 12             | 96                 | 100      |
| 18             | 98                 | 104      |

#### Geo queries with UNF

| Worker threads | Queries per second | % change |
|----------------|--------------------|----------|
| 0              | 61                 | 0        |
| 6              | 227                | 272      |
| 12             | 217                | 256      |
| 18             | 217                | 256      |

code:
FT.CREATE jsonidx:profiles ON JSON PREFIX 1 profiles:
          SCHEMA $.tags.* as t NUMERIC SORTABLE
                 $.firstName as name TEXT
                 $.location as loc GEO

section_id: anti-pattern-index-schema

code: FT.AGGREGATE jsonidx:profiles '@t:[1299 1299]' LOAD * LIMIT 0 10

section_id: anti-pattern-query

code:
FT.CREATE jsonidx:profiles ON JSON PREFIX 1 profiles:
          SCHEMA $.tags.* as t NUMERIC SORTABLE
                 $.firstName as name TEXT NOSTEM SORTABLE
                 $.lastName as lastname TEXT NOSTEM SORTABLE
                 $.location as loc GEO SORTABLE
                 $.id as id TAG SORTABLE UNF
                 $.ver as ver TAG SORTABLE UNF

section_id: improved-index-schema

code:
FT.AGGREGATE jsonidx:profiles '@t:[1299 1299]'
                LOAD 6 id t name lastname loc ver
                LIMIT 0 10
                DIALECT 3

section_id: improved-query


title: Search and query Active-Active databases

title: Overview

text:
Starting with RediSearch 2.x, supported in Redis Software (RS) 6.0 and later, you can [enable search and query]() for [Active-Active databases]() at the time of creation.

You can run search operations on any instance of an Active-Active database.

title: How it works

text:
1. Create an Active-Active database with RediSearch 2.x enabled. Active-Active databases created with or upgraded to Redis version 8 or later automatically enable search and query.
1. [Create the index]() on each instance of the database.
1. If you are using [synonyms](), you need to add them to each replica.
1. The index is maintained by each instance outside of the database keyspace, so only updates to the hashes in the databases are synchronized.

title: Command compatibility

role: syntax

text:
Active-Active databases do not support the following search and query commands:

- [`FT.DROPINDEX` ]()
- [`FT.SUGADD`]()
- [`FT.SUGGET`]()
- [`FT.SUGDEL`]()
- [`FT.SUGLEN`]()

title: Example

text:
Here's an example to help visualize Active-Active search and query:

| Time  | Description | CRDB Instance1 | RediSearch Instance 1 | CRDB Instance 2 | RediSearch Instance 2 |
| :---: | :--- | :--- | :--- | :--- | :--- |
|  t0 | Create the index on each instance |  | FT.CREATE idx .... |  | FT.CREATE idx .... |
|  t1 | Add doc1 as a hash on instance 1; RediSearch indexes doc1 on instance 1 | HSET doc1 field1 "a" | (Index doc1 field1 "a") |  |  |
|  t2 | Add doc2 as a hash on instance 2; RediSearch indexes doc2 on instance 2 |  |  | HSET doc1 field2 "b" | (Index doc1 field2 "b") |
|  t3 | Searching for "a" in each instance only finds the result in instance 1 |  | FT.Search idx "a"
1) 1
2) doc1 |  | FT.Search idx "a"
1) 0 |
|  t4 | Active-Active synchronization | - Sync - |  | - Sync - |  |
|  t5 | Both hashes are found in each instance | HGETALL doc1
1) "field2"
2) "b"
3) "field1"
4) "a" |  | HGETALL doc1
1) "field2"
2) "b"
3) "field1"
4) "a" |  |
|  t6 | Searching for "a" in each instance finds both documents |  | FT.Search idx "a"
1) 1
2) doc1 |  | FT.Search idx "a"
1) 1
2) doc1 |

The practical result is that you have a geo-distributed database with a high level of consistency that can also run search operations on any instance.


title: Redis Open Source quick start

title: Overview

text:
To quickly set up a database with Redis Stack (Redis Open Source) features,
you can sign up for a free [Redis Cloud](https://cloud.redis.io/#/sign-up) subscription and create a Redis Stack database.

Alternatively, you can use one of these methods:

- [Redis Software]()
- Redis Software in a [Docker container]()
- [Other platforms]() for Redis Software

title: Set up a Redis Cloud database

text:
To set up a Redis Cloud database with Redis Stack features, follow these steps:

1. [Create a new Redis Cloud subscription](#create-a-subscription).

1. [Create a Redis Stack database](#create-a-redis-stack-database).

1. [Connect to the database](#connect-to-the-database).

For more details, see the Redis Cloud [quick start]().

title: Create a subscription

text:
To create a new subscription:

1. Sign in to the Redis Cloud [admin console](http://cloud.redis.io) or create a new account.

1. Select the **New subscription** button:

1. Configure your subscription:

    1. Select **Fixed plans**.
    1. For the cloud vendor, select **Amazon Web Services** (AWS), **Google Cloud** (GCP), or **Microsoft Azure**.
    1. Select a region to deploy the subscription to.
    1. From the dataset size list, select the Free tier (30MB).
    1. Enter a name for the subscription.

1. Select the **Create subscription** button:

title: Create a Redis Stack database

text:
After you create a subscription, follow these steps to create a Redis Stack database:

1. Select the **New database** button:

1. In **General** settings, enter a **Database name**.

1. For database **Type**, select **Redis Stack**.

1. Select the **Activate database** button:

title: Connect to the database

text:
After creating the database, you can view its **Configuration** settings. You will need the following information to connect to your new database:

- **Public endpoint**: The host address of the database
- **Redis password**/**Default user password**: The password used to authenticate with the database

With this information, you can connect to your database with the [`redis-cli`]() command-line tool, an application, or [Redis Insight](https://redislabs.com/redisinsight/).

title: Try Redis Open Source features

text:
To try out Redis Open Source features, follow the examples provided by the corresponding guides:

- [Redis Search quick start]()
- [JSON quick start](#use-redisjson)
- [Time series quick start]()
- [Probabilistic data structures quick start]()


title: Time series commands

summary: Lists time series commands and provides links to the command reference pages.

title: Content

text:
The following table lists time series commands. See the command links for more information about each command's syntax, arguments, and examples.

| Command | Redis
Software | Redis
Cloud | Description |
|:--------|:----------------------|:-----------------|:------|
| [TS.ADD]() | ✅ Supported

 | <nobr>✅ Flexible & Annual</nobr>
✅ Free & Fixed</nobr> | Appends a sample to a time series. |
| [TS.ALTER]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Updates the retention, chunk size, duplicate policy, or labels for an existing time series. |
| [TS.CREATE]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Creates a new time series. |
| [TS.CREATERULE]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Creates a compaction rule for [downsampling](). |
| [TS.DECRBY]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Decreases the value of the latest sample in a time series by the specified number. Either modifies the existing sample or adds the decreased value as a new sample, depending on the timestamp option. |
| [TS.DEL]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Removes all samples between two timestamps for a given time series. |
| [TS.DELETERULE]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Removes a compaction rule. |
| [TS.GET]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Returns the last sample in a time series. |
| [TS.INCRBY]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Increases the value of the latest sample in a time series by the specified number. Either modifies the existing sample or adds the increased value as a new sample, depending on the timestamp option. |
| [TS.INFO]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Returns time series information and statistics. |
| [TS.MADD]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Appends multiple samples to one or more time series. |
| [TS.MGET]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Returns multiple samples with [labels]() that match the filter. |
| [TS.MRANGE]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | For multiple time series, runs a query against samples within a range of timestamps, from earliest to latest. Supports [filtering]() and [aggregation](). |
| [TS.MREVRANGE]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | For multiple time series, runs a query against samples within a range of timestamps in reverse order, from latest to earliest. Supports [filtering]() and [aggregation](). |
| [TS.QUERYINDEX]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | Returns the keys of all time series with [labels]() that match the given filters. |
| [TS.RANGE]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | From the start of a single time series, runs a query against samples within a range of timestamps. Supports [filtering]() and [aggregation](). |
| [TS.REVRANGE]() | ✅ Supported

 | ✅ Flexible & Annual
✅ Free & Fixed</nobr> | From the end of a single time series, runs a query against samples within a range of timestamps in reverse order. Supports [filtering]() and [aggregation](). |


title: Time series configuration compatibility with Redis Software

summary: Time series configuration settings supported by Redis Software and Redis Cloud.

title: Configure time series in Redis Software

text:
[Redis Software]() lets you manually change any [RedisTimeSeries configuration setting](configuration/#redistimeseries-configuration-parameters).

To change RedisTimeSeries configuration using the Redis Software Cluster Manager UI:

  1. From the **Databases** list, select the database, then click **Configuration**.

  1. Select the **Edit** button.

  1. In the **Capabilities** section, click **Parameters**.

  1. After you finish editing the module's configuration parameters, click **Done** to close the parameter editor.

  1. Click **Save**.

title: Configure time series in Redis Cloud

text: [Redis Cloud]() does not let you configure RedisTimeSeries manually. However, if you have a Flexible or Annual [subscription](), you can contact [support](https://redis.com/company/support/) to request a configuration change. You cannot change RedisTimeSeries configuration for Free or Fixed subscriptions.

title: Configuration settings

text: See [configuration parameters]() in the Develop section for parameter details and compatibility with Redis Software and Redis Cloud.


title: Time series

title: Time series commands

title: Overview

text: You can manage time series data in Redis Software with Redis Open Source.

title: Features

text:
- Query by start time and end-time
- Query by labels sets
- Aggregated queries (Min, Max, Avg, Sum, Range, Count, First, Last) for any time bucket
- Configurable max retention period
- Compaction/Roll-ups - automatically updated aggregated time series
- labels index - each key has labels which allows query by labels

title: Memory model

text:
A time series is a linked list of memory chunks.
Each chunk has a predefined size of samples.
Each sample is a tuple of the time and the value of 128 bits,
64 bits for the timestamp and 64 bits for the value.

title: Time series capabilities

text: Redis Open Source provides a new data type that uses chunks of memory of fixed size for time series samples, indexed by the same Radix Tree implementation as Redis streams. With streams, you can create [a capped stream](), effectively limiting the number of messages by count. For time series, you can apply a retention policy in milliseconds. This is better for time series use cases, because they are typically interested in the data during a given time window, rather than a fixed number of samples.

title: Downsampling/compaction

text:
| Before Downsampling | After Downsampling |
| --- | --- |
|  |  |

If you want to keep all of your raw data points indefinitely, your data set grows linearly over time. However, if your use case allows you to have less fine-grained data further back in time, downsampling can be applied. This allows you to keep fewer historical data points by aggregating raw data for a given time window using a given aggregation function. Time series support [downsampling]() with the following aggregations: avg, sum, min, max, range, count, first, and last.

title: Secondary indexing

text:
When using Redis’ core data structures, you can only retrieve a time series by knowing the exact key holding the time series. Unfortunately, for many time series use cases (such as root cause analysis or monitoring), your application won’t know the exact key it’s looking for. These use cases typically want to query a set of time series that relate to each other in a couple of dimensions to extract the insight you need. You could create your own secondary index with core Redis data structures to help with this, but it would come with a high development cost and require you to manage edge cases to make sure the index is correct.

Redis does this indexing for you based on `field value` pairs called [labels](). You can add labels to each time series and use them to [filter]() at query time.

Here’s an example of creating a time series with two labels (sensor_id and area_id are the fields with values 2 and 32 respectively) and a retention window of 60,000 milliseconds:

[code example]

title: Aggregation at read time

text:
When you need to query a time series, it’s cumbersome to stream all raw data points if you’re only interested in, say, an average over a given time interval. Time series only transfer the minimum required data to ensure lowest latency.

Here's an example of [aggregation]() over time buckets of 5,000 milliseconds:

[code example]

title: Integrations

text:
Redis Open Source comes with several integrations into existing time series tools. One such integration is our [RedisTimeSeries adapter](https://github.com/RedisTimeSeries/prometheus-redistimeseries-adapter) for [Prometheus](https://prometheus.io/), which keeps all your monitoring metrics inside time series while leveraging the entire [Prometheus ecosystem](https://prometheus.io/docs/prometheus/latest/storage/#remote-storage-integrations).

Furthermore, we also created direct integrations for [Grafana](https://github.com/RedisTimeSeries/grafana-redistimeseries). [This repository](https://github.com/RedisTimeSeries/prometheus-demos) contains a docker-compose setup of RedisTimeSeries, its remote write adaptor, Prometheus and [Grafana](https://grafana.com/). It also comes with a set of data generators and pre-built Grafana dashboards.

title: Time series modeling approaches with Redis

title: Data modeling approaches

text:
Redis streams allow you to add several field value pairs in a message for a given timestamp. For each device, we collected 10 metrics that were modeled as 10 separate fields in a single stream message.

For sorted sets, we modeled the data in two different ways. For "Sorted set per device", we concatenated the metrics and separated them out by colons, e.g. `"<timestamp>:<metric1>:<metric2>: … :<metric10>"`.

Of course, this consumes less memory but needs more CPU cycles to get the correct metric at read time. It also implies that changing the number of metrics per device isn’t straightforward, which is why we also benchmarked a second sorted set approach. In "Sorted set per metric," we kept each metric in its own sorted set and had 10 sorted sets per device. We logged values in the format `"<timestamp>:<metric>"`.

Another alternative approach would be to normalize the data by creating a hash with a unique key to track all measurements for a given device for a given timestamp. This key would then be the value in the sorted set. However, having to access many hashes to read a time series would come at a huge cost during read time, so we abandoned this path.

Each time series holds a single metric. We chose this design to maintain the Redis principle that a larger number of small keys is better than a fewer number of large keys.

Our benchmark did not utilize the out-of-the-box secondary indexing capabilities of time series. Redis keeps a partial secondary index in each shard, and since the index inherits the same hash-slot of the key it indexes, it is always hosted on the same shard. This approach would make the setup for native data structures even more complex to model, so for the sake of simplicity, we decided not to include it in our benchmarks. Additionally, while Redis Software can use the [proxy](https://redis.com/redis-enterprise/technology/redis-enterprise-cluster-architecture/) to fan out requests for commands like [TS.MGET]() and [TS.MRANGE]() to all the shards and aggregate the results, we chose not to exploit this advantage in the benchmark either.

title: Data ingestion

text:
For the data ingestion part of our benchmark, we compared the four approaches by measuring how many devices’ data we could ingest per second. Our client side had 8 worker threads with 50 connections each, and a pipeline of 50 commands per request.

Ingestion details of each approach:

|                         | **Redis streams** | **Time series** | **Sorted set
per device** | **Sorted set
per metric** |
| ----------------------- | ----------------- | ------------------- | ----------------------------- | ----------------------------- |
| **Command**             | XADD              | TS.MADD             | ZADD                          | ZADD                          |
| **Pipeline**            | 50                | 50                  | 50                            | 50                            |
| **Metrics per request** | 5000              | 5000                | 5000                          | 500                           |
| **# keys**              | 4000              | 40000               | 4000                          | 40000                         |

All our ingestion operations were executed at sub-millisecond latency. Although both used the same Rax data structure, the time series approach has slightly higher throughput than Redis streams.

Each approach yields different results, which shows the value of prototyping against specific use cases. As we see on query performance, the sorted set per device comes with improved write throughput but at the expense of query performance. It’s a trade off between ingestion, query performance, and flexibility (remember the earlier data modeling remark).

title: Read performance

text:
The read query we used in this benchmark queried a single time series and aggregated it in one-hour time buckets by keeping the maximum observed CPU percentage in each bucket. The time range we considered in the query was exactly one hour, so a single maximum value was returned. For time series, this is out of the box functionality.

[code example]

For the Redis streams and sorted sets approaches, we created [the following LUA scripts](https://gist.github.com/itamarhaber/0107020b91c71cb52e57e9a9c890c24e). The client once again had 8 threads and 50 connections each. Since we executed the same query, only a single shard was hit, and in all four cases this shard maxed out at 100% CPU.

This is where you can see the real power of having dedicated data structure for a given use case with a toolbox that runs alongside it. Using time series exceeds all other approaches and is the only one to achieve sub-millisecond response times.

title: Memory utilization

text:
For both the Redis streams and sorted set approaches, the samples were stored as strings, while time series stored them as doubles. In this specific data set, we chose a CPU measurement with rounded integer values between 0-100, which thus consumes two bytes of memory as a string. With time series, each metric had 64-bit precision.

Time series can dramatically reduce the memory consumption when compared against both sorted set approaches. Given the unbounded nature of time series data, this is typically a critical criteria to evaluate - the overall data set size that needs to be retained in memory. Redis streams reduces the memory consumption further but would be equal or higher than time series when more digits for a higher precision would be required.

title: More info

text:
- [Time series quick start]()
- [Time series commands]()
- [Time series configuration]()
- [RedisTimeSeries source](https://github.com/RedisTimeSeries/RedisTimeSeries)

code: TS.CREATE temperature RETENTION 60000 LABELS sensor_id 2 area_id 32

section_id: secondary-indexing

section_id: aggregation-at-read-time

section_id: read-performance