XREADGROUP

Summary: Returns new or historical messages from a stream for a consumer in a group. Blocks until a message is available otherwise.

Overview

This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

The `XREADGROUP` command is a special version of the [`XREAD`]() command
with support for consumer groups. Probably you will have to understand the
[`XREAD`]() command before reading this page will makes sense.

Moreover, if you are new to streams, we recommend to read our
[introduction to Redis Streams]().
Make sure to understand the concept of consumer group in the introduction
so that following how this command works will be simpler.

Consumer groups in 30 seconds

The difference between this command and the vanilla [`XREAD`]() is that this
one supports consumer groups.

Without consumer groups, just using [`XREAD`](), all the clients are served with all the entries arriving in a stream. Instead using consumer groups with `XREADGROUP`, it is possible to create groups of clients that consume different parts of the messages arriving in a given stream. If, for instance, the stream gets the new entries A, B, and C and there are two consumers reading via a consumer group, one client will get, for instance, the messages A and C, and the other the message B, and so forth.

Within a consumer group, a given consumer (that is, just a client consuming messages from the stream), has to identify with a unique *consumer name*. Which is just a string.

One of the guarantees of consumer groups is that a given consumer can only see the history of messages that were delivered to it, so a message has just a single owner. However there is a special feature called *message claiming* that allows other consumers to claim messages in case there is a non recoverable failure of some consumer. In order to implement such semantics, consumer groups require explicit acknowledgment of the messages successfully processed by the consumer, via the [`XACK`]() command. This is needed because the stream will track, for each consumer group, who is processing what message.

This is how to understand if you want to use a consumer group or not:

1. If you have a stream and multiple clients, and you want all the clients to get all the messages, you do not need a consumer group.
2. If you have a stream and multiple clients, and you want the stream to be *partitioned* or *sharded* across your clients, so that each client will get a sub set of the messages arriving in a stream, you need a consumer group.

Differences between XREAD and XREADGROUP

From the point of view of the syntax, the commands are almost the same,
however `XREADGROUP` *requires* a special and mandatory option:

    GROUP <group-name> <consumer-name>

The group name is just the name of a consumer group associated to the stream.
The group is created using the [`XGROUP`]() command. The consumer name is the
string that is used by the client to identify itself inside the group.
The consumer is auto created inside the consumer group the first time it
is seen. Different clients should select a different consumer name.

When you read with `XREADGROUP`, the server will *remember* that a given
message was delivered to you: the message will be stored inside the
consumer group in what is called a Pending Entries List (PEL), that is
a list of message IDs delivered but not yet acknowledged.

The client will have to acknowledge the message processing using [`XACK`]()
in order for the pending entry to be removed from the PEL. The PEL
can be inspected using the [`XPENDING`]() command.

The `NOACK` subcommand can be used to avoid adding the message to the PEL in
cases where reliability is not a requirement and the occasional message loss
is acceptable. This is equivalent to acknowledging the message when it is read.
When used together with `CLAIM`, `NOACK` does not apply for retrieved pending entries.

The ID to specify in the **STREAMS** option when using `XREADGROUP` can
be one of the following two:

* When the special `>` id is specified without `CLAIM`, the consumer wants to receive only messages that were never delivered to any other consumer, hence, just new messages.
* When the special `>` id is specified with `CLAIM`, the consumer wants, in addition, to receive messages that have been delivered to some consumer and have been pending for at least min-idle-time milliseconds.
* Any other ID, that is, 0 or any other valid ID or incomplete ID (just the millisecond time part), will have the effect of returning entries that are pending for the consumer sending the command with IDs greater than the one provided. So basically if the ID is not `>`, then the command will just let the client access its pending entries: messages delivered to it, but not yet acknowledged. Note that in this case, `BLOCK`, `NOACK`, and `CLAIM` are ignored.

Like [`XREAD`]() the `XREADGROUP` command can be used in a blocking way. There
are no differences in this regard.

The CLAIM option

The `CLAIM` option was added as part of Redis 8.4. When `CLAIM min-idle-time` is specified, Redis will first try to claim messages which have been pending for at least min-idle-time milliseconds from the consumer group of each specified stream key. The pending messages with the highest idle time would be claimed first. Note that the `CLAIM min-idle-time` condition may become true for some pending entries during the `BLOCK milliseconds` period (if specified).

If there are no such messages, Redis will continue as normal (consume incoming messages).

`CLAIM min-idle-time` is ignored if the specified id is not `>`.

Reply extension for claimed entries

When `CLAIM min-idle-time` is used, additional information is provided for each pending entry retrieved (similar to the reply of [`XPENDING`]()). For each claimed pending entry, the reply includes:

1. Entry id
2. Field-value pairs
3. Milliseconds since the last time this entry was delivered
4. Number of times this entry was previously delivered

Ordering guarantees

Within each stream, entries are reported in the same order they were added by `XADD` (older first).

When not blocked, across streams, entries are reported in the order the streams were specified.

When using `CLAIM`, the following ordering guarantees apply per stream:

- Idle pending entries are reported first, then incoming entries
- Idle pending entries are ordered by idle time (longer first)
- Incoming entries are reported in the order they were added by `XADD` (older first)

For example, if there are 20 idle pending entries and 200 incoming entries (in all the specified streams together):
- When calling `XREADGROUP ... CLAIM ...`, you would retrieve 220 entries in the reply
- When calling `XREADGROUP ... COUNT 100 ... CLAIM ...`, you would retrieve the 20 idle pending entries + 80 incoming entries in the reply

What happens when a message is delivered to a consumer?

Two things:

1. If the message was never delivered to anyone, that is, if we are talking about a new message, then a PEL (Pending Entries List) is created.
2. If instead the message was already delivered to this consumer, and it is just re-fetching the same message again, then the *last delivery counter* is updated to the current time, and the *number of deliveries* is incremented by one. You can access those message properties using the [`XPENDING`]() command.

Usage example

Normally you use the command like that in order to get new messages and
process them. In pseudo-code:

[code example]

In this way the example consumer code will fetch only new messages, process
them, and acknowledge them via [`XACK`](). However the example code above is
not complete, because it does not handle recovering after a crash. What
will happen if we crash in the middle of processing messages, is that our
messages will remain in the pending entries list, so we can access our
history by giving `XREADGROUP` initially an ID of 0, and performing the same
loop. Once providing an ID of 0 the reply is an empty set of messages, we
know that we processed and acknowledged all the pending messages: we
can start to use `>` as ID, in order to get the new messages and rejoin the
consumers that are processing new things.

To see how the command actually replies, please check the [`XREAD`]() command page.

What happens when a pending message is deleted?

Entries may be deleted from the stream due to trimming with [`XADD`]() or [`XTRIM`](),
or explicit calls to [`XDEL`](), [`XDELEX`](), or [`XACKDEL`]().

When an entry is trimmed with [`XADD`]() or [`XTRIM`]() and `DELREF` or `ACKED` are not specified,
deleted with [`XDEL`](), or deleted with [`XDELEX`]() or [`XACKDEL`]()
and `DELREF` or `ACKED` are not specified, Redis doesn't prevent the deletion of entries that are present in the stream's PELs.
When this happens, the PELs retain the deleted entries' IDs, but the actual entry payload is no longer available.
Therefore, when reading such PEL entries, Redis will return a null value in place of their respective data.

Example:

[code example]

Reading the [Redis Streams introduction]() is highly
suggested in order to understand more about the streams overall behavior
and semantics.

| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

Return information

WHILE true
    entries = XREADGROUP GROUP $GroupName $ConsumerName BLOCK 2000 COUNT 10 STREAMS mystream >
    if entries == nil
        puts "Timeout... try again"
        CONTINUE
    end

    FOREACH entries AS stream_entries
        FOREACH stream_entries as message
            process_message(message.id,message.fields)

            # ACK the message as processed
            XACK mystream $GroupName message.id
        END
    END
END

> XADD mystream 1 myfield mydata
"1-0"
> XGROUP CREATE mystream mygroup 0
OK
> XREADGROUP GROUP mygroup myconsumer STREAMS mystream >
1) 1) "mystream"
   2) 1) 1) "1-0"
         2) 1) "myfield"
            2) "mydata"
> XDEL mystream 1-0
(integer) 1
> XREADGROUP GROUP mygroup myconsumer STREAMS mystream 0
1) 1) "mystream"
   2) 1) 1) "1-0"
         2) (nil)


XREVRANGE

Summary: Returns the messages from a stream within a range of IDs in reverse order.

Overview

This command is exactly like [`XRANGE`](), but with the notable difference of
returning the entries in reverse order, and also taking the start-end
range in reverse order: in `XREVRANGE` you need to state the *end* ID
and later the *start* ID, and the command will produce all the element
between (or exactly like) the two IDs, starting from the *end* side.

So for instance, to get all the elements from the higher ID to the lower
ID one could use:

    XREVRANGE somestream + -

Similarly to get just the last element added into the stream it is
enough to send:

    XREVRANGE somestream + - COUNT 1

Examples

XADD writers * name Virginia surname Woolf
XADD writers * name Jane surname Austen
XADD writers * name Toni surname Morrison
XADD writers * name Agatha surname Christie
XADD writers * name Ngozi surname Adichie
XLEN writers
XREVRANGE writers + - COUNT 1

Redis Software and Redis Cloud compatibility

Return information

**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): The command returns the entries with IDs matching the specified range. The returned entries are complete, which means that the ID and all the fields they are composed of are returned. Moreover, the entries are returned with their fields and values in the same order as `XADD` added them.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): The command returns the entries with IDs matching the specified range. The returned entries are complete, which means that the ID and all the fields they are composed of are returned. Moreover, the entries are returned with their fields and values in the same order as `XADD` added them.


XSETID

Summary: An internal command for replicating stream values.

Overview

The `XSETID` command is an internal command.
It is used by a Redis master to replicate the last delivered ID of streams.

Return information

**RESP2:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK`.

**RESP3:**

[Simple string reply](../../develop/reference/protocol-spec#simple-strings): `OK`.


XTRIM

Summary: Deletes messages from the beginning of a stream.

Overview

`XTRIM` trims the stream by evicting older entries (entries with lower IDs) if needed.

Required arguments

key

The name of the stream key.

MAXLEN | MINID

The trimming strategy:
- `MAXLEN`: Evicts entries as long as the stream's length exceeds the specified threshold
- `MINID`: Evicts entries with IDs lower than the specified threshold (available since Redis 6.2.0)

threshold

The trimming threshold:
- For `MAXLEN`: `threshold` is a non-negative integer specifying the maximum number of entries that may remain in the stream after trimming. Redis enforces this by removing the oldest entries - that is, the entries with the lowest stream IDs - so that only the newest entries are kept.
- For `MINID`: `threshold` is a stream ID. All entries whose IDs are less than `threshold` are trimmed. All entries with IDs greater than or equal to `threshold` are kept.

Optional arguments

= | ~

The trimming operator:
- `=`: Exact trimming (default) - trims to the exact threshold
- `~`: Approximate trimming - more efficient, may leave slightly more entries than the threshold

LIMIT count

Limits the number of entries to examine during trimming. Available since Redis 6.2.0. When not specified, Redis uses a default value of 100 * the number of entries in a macro node. Specifying 0 disables the limiting mechanism entirely.

KEEPREF | DELREF | ACKED

Specifies how to handle consumer group references when trimming. If there are no consumer groups, these arguments have no effect. Available since Redis 8.2.

If no option is specified, `KEEPREF` is used by default. Unlike the `XDELEX` and `XACKDEL` commands where one of these options is required, here they are optional to maintain backward compatibility:

- `KEEPREF` (default): When trimming, removes entries from the stream according to the specified strategy (`MAXLEN` or `MINID`), regardless of whether they are referenced by any consumer groups, but preserves existing references to these entries in all consumer groups' PEL (Pending Entries List).
- `DELREF`: When trimming, removes entries from the stream according to the specified strategy and also removes all references to these entries from all consumer groups' PEL.
- `ACKED`: When trimming, only removes entries that were read and acknowledged by all consumer groups. Note that if the number of referenced entries is larger than `MAXLEN`, trimming will still stop at the limit.

For example, this trims the stream to exactly the latest 1000 items:

[code example]

In this example, Redis evicts all entries that have an ID lower than 649085820-0:

[code example]

By default, or when you provide the optional `=` argument, the command performs exact trimming.

Depending on the strategy, exact trimming means:

* `MAXLEN`: The trimmed stream's length will be exactly the minimum between its original length and the specified `threshold`.
* `MINID`: The oldest ID in the stream will be exactly the maximum between its original oldest ID and the specified `threshold`.

Nearly exact trimming
---

Because exact trimming may require additional effort from the Redis server, you can provide the optional `~` argument to make it more efficient.

For example:

[code example]

The `~` argument between the `MAXLEN` strategy and the `threshold` means that you are requesting to trim the stream so its length is **at least** the `threshold`, but possibly slightly more.
In this case, Redis stops trimming early when performance can be gained (for example, when a whole macro node in the data structure can't be removed).
This makes trimming much more efficient, and it is usually what you want, although after trimming, the stream may have a few tens of additional entries over the `threshold`.

Another way to control the amount of work done by the command when using `~` is the `LIMIT` clause.
When you use it, it specifies the maximum `count` of entries that will be evicted.
When you don't specify `LIMIT` and `count`, Redis implicitly uses the default value of 100 * the number of entries in a macro node as the `count`.
Specifying the value 0 as `count` disables the limiting mechanism entirely.

Examples

XADD mystream * field1 A field2 B field3 C field4 D
XTRIM mystream MAXLEN 2
XRANGE mystream - +

Return information

**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): The number of entries deleted from the stream.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): The number of entries deleted from the stream.


ZADD

Summary: Adds one or more members to a sorted set, or updates their scores. Creates the key if it doesn't exist.

Examples

#### Code Examples

Foundational: Add one or more members to a sorted set with scores using ZADD (creates sorted set if needed, updates scores if member exists)

**Difficulty:** Beginner

**Commands:** ZADD, ZRANGE

**Complexity:**
- ZADD: O(log(N)
- ZRANGE: O(log(N)

**Redis CLI:**

[code example]

**Available in:** Redis CLI, C# (Synchronous), Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python

**C# (Synchronous):**

[code example]

**Go:**

[code example]

**Java (Synchronous - Jedis):**

[code example]

**JavaScript (Node.js):**

[code example]

**Python:**

[code example]

Give these commands a try in the interactive console:

ZADD myzset 1 "one"
ZADD myzset 1 "uno"
ZADD myzset 2 "two" 3 "three"
ZRANGE myzset 0 -1 WITHSCORES

Return information

**RESP2:**

Any of the following:
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if the operation was aborted because of a conflict with one of the _XX/NX/LT/GT_ options.
* [Integer reply](../../develop/reference/protocol-spec#integers): the number of new members when the _CH_ option is not used.
* [Integer reply](../../develop/reference/protocol-spec#integers): the number of new or updated members when the _CH_ option is used.
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the updated score of the member when the _INCR_ option is used.

**RESP3:**

Any of the following:
* [Null reply](../../develop/reference/protocol-spec#nulls): if the operation was aborted because of a conflict with one of the _XX/NX/LT/GT_ options.
* [Integer reply](../../develop/reference/protocol-spec#integers): the number of new members when the _CH_ option is not used.
* [Integer reply](../../develop/reference/protocol-spec#integers): the number of new or updated members when the _CH_ option is used.
* [Double reply](../../develop/reference/protocol-spec#doubles): the updated score of the member when the _INCR_ option is used.

> ZADD myzset 1 "one"
(integer) 1
> ZADD myzset 1 "uno"
(integer) 1
> ZADD myzset 2 "two" 3 "three"
(integer) 2
> ZRANGE myzset 0 -1 WITHSCORES
1) "one"
2) "1"
3) "uno"
4) "1"
5) "two"
6) "2"
7) "three"
8) "3"

bool zAddResult1 = db.SortedSetAdd("myzset", "one", 1);
        Console.WriteLine(zAddResult1); // >>> True

        bool zAddResult2 = db.SortedSetAdd("myzset", "uno", 1);
        Console.WriteLine(zAddResult2); // >>> True

        long zAddResult3 = db.SortedSetAdd(
            "myzset",
            [
                new("two", 2),
                new("three", 3)
            ]
        );
        Console.WriteLine(zAddResult3); // >>> 2

        SortedSetEntry[] zAddResult4 = db.SortedSetRangeByRankWithScores("myzset", 0, -1);
        Console.WriteLine($"{string.Join(", ", zAddResult4.Select(b => $"{b.Element}: {b.Score}"))}");
        // >>> one: 1, uno: 1, two: 2, three: 3

zAddResult1, err := rdb.ZAdd(ctx, "myzset",
		redis.Z{Member: "one", Score: 1},
	).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zAddResult1) // >>> 1

	zAddResult2, err := rdb.ZAdd(ctx, "myzset",
		redis.Z{Member: "uno", Score: 1},
	).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zAddResult2)

	zAddResult3, err := rdb.ZAdd(ctx, "myzset",
		redis.Z{Member: "two", Score: 2},
		redis.Z{Member: "three", Score: 3},
	).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zAddResult3) // >>> 2

	zAddResult4, err := rdb.ZRangeWithScores(ctx, "myzset", 0, -1).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zAddResult4) // >>> [{1 one} {1 uno} {2 two} {3 three}]

Map<String, Double> zAddExampleParams = new HashMap<>();
        zAddExampleParams.put("one", 1.0);
        long zAddResult1 = jedis.zadd("myzset", zAddExampleParams);
        System.out.println(zAddResult1);    // >>> 1

        zAddExampleParams.clear();
        zAddExampleParams.put("uno", 1.0);
        long zAddResult2 = jedis.zadd("myzset", zAddExampleParams);
        System.out.println(zAddResult2);    // >>> 1

        zAddExampleParams.clear();
        zAddExampleParams.put("two", 2.0);
        zAddExampleParams.put("three", 3.0);
        long zAddResult3 = jedis.zadd("myzset", zAddExampleParams);
        System.out.println(zAddResult3);    // >>> 2

        List<Tuple> zAddResult4 = jedis.zrangeWithScores("myzset", new ZRangeParams(0, -1));

        for (Tuple item: zAddResult4) {
            System.out.println("Element: " + item.getElement() + ", Score: " + item.getScore());
        }
        // >>> Element: one, Score: 1.0
        // >>> Element: uno, Score: 1.0
        // >>> Element: two, Score: 2.0
        // >>> Element: three, Score: 3.0

const val1 = await client.zAdd("myzset", [{ value: 'one', score: 1 }]);
console.log(val1);
// returns 1

const val2 = await client.zAdd("myzset", [{ value: 'uno', score: 1 }]);
console.log(val2);
// returns 1

const val3 = await client.zAdd("myzset", [{ value: 'two', score: 2 }, { value: 'three', score: 3 }]);
console.log(val3);
// returns 2

const val4 = await client.zRangeWithScores("myzset", 0, -1);
console.log(val4);
// returns [{value: 'one', score: 1}, {value: 'uno', score: 1}, {value: 'two', score: 2}, {value: 'three', score: 3} ]

res = r.zadd("myzset", {"one": 1})
print(res)
# >>> 1

res = r.zadd("myzset", {"uno": 1})
print(res)
# >>> 1

res = r.zadd("myzset", {"two": 2, "three": 3})
print(res)
# >>> 2

res = r.zrange("myzset", 0, -1, withscores=True)
# >>> [('one', 1.0), ('uno', 1.0), ('two', 2.0), ('three', 3.0)]


ZCARD

Summary: Returns the number of members in a sorted set.

Overview

Returns the sorted set cardinality (number of elements) of the sorted set stored
at `key`.

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZCARD myzset

Return information

**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the cardinality (number of members) of the sorted set, or 0 if the key doesn't exist.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the cardinality (number of members) of the sorted set, or 0 if the key doesn't exist.


ZCOUNT

Summary: Returns the count of members in a sorted set that have scores within a range.

Overview

Returns the number of elements in the sorted set at `key` with a score between
`min` and `max`.

The `min` and `max` arguments have the same semantic as described for
[`ZRANGEBYSCORE`]().

Note: the command has a complexity of just O(log(N)) because it uses elements ranks (see [`ZRANK`]()) to get an idea of the range. Because of this there is no need to do a work proportional to the size of the range.

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"
ZCOUNT myzset -inf +inf
ZCOUNT myzset (1 3

| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

Return information

**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members in the specified score range.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members in the specified score range.


ZDIFF

Summary: Returns the difference between multiple sorted sets.

Overview

This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

This command is similar to [`ZDIFFSTORE`](), but instead of storing the resulting
sorted set, it is returned to the client.

Examples

ZADD zset1 1 "one"
ZADD zset1 2 "two"
ZADD zset1 3 "three"
ZADD zset2 1 "one"
ZADD zset2 2 "two"
ZDIFF 2 zset1 zset2
ZDIFF 2 zset1 zset2 WITHSCORES

Return information

**RESP2:**

* [Array reply](../../develop/reference/protocol-spec#arrays): the result of the difference including, optionally, scores when the _WITHSCORES_ option is used.

**RESP3:**

* [Array reply](../../develop/reference/protocol-spec#arrays): the result of the difference including, optionally, scores when the _WITHSCORES_ option is used.


ZDIFFSTORE

Summary: Stores the difference of multiple sorted sets in a key.

Overview

This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

Computes the difference between the first and all successive input sorted sets
and stores the result in `destination`. The total number of input keys is
specified by `numkeys`.

Keys that do not exist are considered to be empty sets.

If `destination` already exists, it is overwritten.

Examples

ZADD zset1 1 "one"
ZADD zset1 2 "two"
ZADD zset1 3 "three"
ZADD zset2 1 "one"
ZADD zset2 2 "two"
ZDIFFSTORE out 2 zset1 zset2
ZRANGE out 0 -1 WITHSCORES

Return information

**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members in the resulting sorted set at _destination_.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members in the resulting sorted set at _destination_.


ZINCRBY

Summary: Increments the score of a member in a sorted set.

Overview

Increments the score of `member` in the sorted set stored at `key` by
`increment`.
If `member` does not exist in the sorted set, it is added with `increment` as
its score (as if its previous score was `0.0`).
If `key` does not exist, a new sorted set with the specified `member` as its
sole member is created.

An error is returned when `key` exists but does not hold a sorted set.

The `score` value should be the string representation of a numeric value, and
accepts double precision floating point numbers.
It is possible to provide a negative value to decrement the score.

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZINCRBY myzset 2 "one"
ZRANGE myzset 0 -1 WITHSCORES

Return information

**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the new score of _member_ as a double precision floating point number.

**RESP3:**

[Double reply](../../develop/reference/protocol-spec#doubles): the new score of _member_.


ZINTER

Summary: Returns the intersect of multiple sorted sets.

Overview

This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

This command is similar to [`ZINTERSTORE`](), but instead of storing the resulting
sorted set, it is returned to the client.

For a description of the `WEIGHTS` and `AGGREGATE` options, see [`ZUNIONSTORE`]().

Examples

ZADD zset1 1 "one"
ZADD zset1 2 "two"
ZADD zset2 1 "one"
ZADD zset2 2 "two"
ZADD zset2 3 "three"
ZINTER 2 zset1 zset2
ZINTER 2 zset1 zset2 WITHSCORES

Return information

**RESP2:**

* [Array reply](../../develop/reference/protocol-spec#arrays): the result of the intersection including, optionally, scores when the _WITHSCORES_ option is used.

**RESP3:**

* [Array reply](../../develop/reference/protocol-spec#arrays): the result of the intersection including, optionally, scores when the _WITHSCORES_ option is used.


ZINTERCARD

Summary: Returns the number of members of the intersect of multiple sorted sets.

Overview

This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

This command is similar to [`ZINTER`](), but instead of returning the result set, it returns just the cardinality of the result.

Keys that do not exist are considered to be empty sets.
With one of the keys being an empty set, the resulting set is also empty (since set intersection with an empty set always results in an empty set).

By default, the command calculates the cardinality of the intersection of all given sets.
When provided with the optional `LIMIT` argument (which defaults to 0 and means unlimited), if the intersection cardinality reaches limit partway through the computation, the algorithm will exit and yield limit as the cardinality.
Such implementation ensures a significant speedup for queries where the limit is lower than the actual intersection cardinality.

Examples

ZADD zset1 1 "one"
ZADD zset1 2 "two"
ZADD zset2 1 "one"
ZADD zset2 2 "two"
ZADD zset2 3 "three"
ZINTER 2 zset1 zset2
ZINTERCARD 2 zset1 zset2
ZINTERCARD 2 zset1 zset2 LIMIT 1

Return information

**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members in the resulting intersection.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members in the resulting intersection.


ZINTERSTORE

Summary: Stores the intersect of multiple sorted sets in a key.

Overview

This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

Computes the intersection of `numkeys` sorted sets given by the specified keys,
and stores the result in `destination`.
It is mandatory to provide the number of input keys (`numkeys`) before passing
the input keys and the other (optional) arguments.

By default, the resulting score of an element is the sum of its scores in the
sorted sets where it exists.
Because intersection requires an element to be a member of every given sorted
set, this results in the score of every element in the resulting sorted set to
be equal to the number of input sorted sets.

For a description of the `WEIGHTS` and `AGGREGATE` options, see [`ZUNIONSTORE`]().

If `destination` already exists, it is overwritten.

Examples

ZADD zset1 1 "one"
ZADD zset1 2 "two"
ZADD zset2 1 "one"
ZADD zset2 2 "two"
ZADD zset2 3 "three"
ZINTERSTORE out 2 zset1 zset2 WEIGHTS 2 3
ZRANGE out 0 -1 WITHSCORES

| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

Return information

**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members in the resulting sorted set at the _destination_.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members in the resulting sorted set at the _destination_.


ZLEXCOUNT

Summary: Returns the number of members in a sorted set within a lexicographical range.

Overview

When all the elements in a sorted set are inserted with the same score, in order to force lexicographical ordering, this command returns the number of elements in the sorted set at `key` with a value between `min` and `max`.

The `min` and `max` arguments have the same meaning as described for
[`ZRANGEBYLEX`]().

Note: the command has a complexity of just O(log(N)) because it uses elements ranks (see [`ZRANK`]()) to get an idea of the range. Because of this there is no need to do a work proportional to the size of the range.

Examples

ZADD myzset 0 a 0 b 0 c 0 d 0 e
ZADD myzset 0 f 0 g
ZLEXCOUNT myzset - +
ZLEXCOUNT myzset [b [f

Return information

**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members in the specified score range.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members in the specified score range.


ZMPOP

Summary: Returns the highest- or lowest-scoring members from one or more sorted sets after removing them. Deletes the sorted set if the last member was popped.

Overview

This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

Pops one or more elements, that are member-score pairs, from the first non-empty sorted set in the provided list of key names.

`ZMPOP` and [`BZMPOP`]() are similar to the following, more limited, commands:

- [`ZPOPMIN`]() or [`ZPOPMAX`]() which take only one key, and can return multiple elements.
- [`BZPOPMIN`]() or [`BZPOPMAX`]() which take multiple keys, but return only one element from just one key.

See [`BZMPOP`]() for the blocking variant of this command.

When the `MIN` modifier is used, the elements popped are those with the lowest scores from the first non-empty sorted set. The `MAX` modifier causes elements with the highest scores to be popped.
The optional `COUNT` can be used to specify the number of elements to pop, and is set to 1 by default.

The number of popped elements is the minimum from the sorted set's cardinality and `COUNT`'s value.

Examples

ZMPOP 1 notsuchkey MIN
ZADD myzset 1 "one" 2 "two" 3 "three"
ZMPOP 1 myzset MIN
ZRANGE myzset 0 -1 WITHSCORES
ZMPOP 1 myzset MAX COUNT 10
ZADD myzset2 4 "four" 5 "five" 6 "six"
ZMPOP 2 myzset myzset2 MIN COUNT 10
ZRANGE myzset 0 -1 WITHSCORES
ZMPOP 2 myzset myzset2 MAX COUNT 10
ZRANGE myzset2 0 -1 WITHSCORES
EXISTS myzset myzset2

Return information

**RESP2:**

One of the following:
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): when no element could be popped.
* [Array reply](../../develop/reference/protocol-spec#arrays): A two-element array with the first element being the name of the key from which elements were popped, and the second element is an array of the popped elements. Every entry in the elements array is also an array that contains the member and its score.

**RESP3:**

One of the following:
* [Null reply](../../develop/reference/protocol-spec#nulls): when no element could be popped.
* [Array reply](../../develop/reference/protocol-spec#arrays): A two-element array with the first element being the name of the key from which elements were popped, and the second element is an array of the popped elements. Every entry in the elements array is also an array that contains the member and its score.


ZMSCORE

Summary: Returns the score of one or more members in a sorted set.

Overview

Returns the scores associated with the specified `members` in the sorted set stored at `key`.

For every `member` that does not exist in the sorted set, a `nil` value is returned.

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZMSCORE myzset "one" "two" "nofield"

Return information

**RESP2:**

One of the following:
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if the member does not exist in the sorted set.
* [Array reply](../../develop/reference/protocol-spec#arrays): a list of [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings) _member_ scores as double-precision floating point numbers.

**RESP3:**

One of the following:
* [Null reply](../../develop/reference/protocol-spec#nulls): if the member does not exist in the sorted set.
* [Array reply](../../develop/reference/protocol-spec#arrays): a list of [Double reply](../../develop/reference/protocol-spec#doubles) _member_ scores as double-precision floating point numbers.


ZPOPMAX

Summary: Returns the highest-scoring members from a sorted set after removing them. Deletes the sorted set if the last member was popped.

Overview

Removes and returns up to `count` members with the highest scores in the sorted
set stored at `key`.

When left unspecified, the default value for `count` is 1. Specifying a `count`
value that is higher than the sorted set's cardinality will not produce an
error. When returning multiple elements, the one with the highest score will
be the first, followed by the elements with lower scores.

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"
ZPOPMAX myzset

Return information

**RESP2:**

* [Array reply](../../develop/reference/protocol-spec#arrays): a list of popped elements and scores.

**RESP3:**

* [Array reply](../../develop/reference/protocol-spec#arrays): a list of popped elements and scores.


ZPOPMIN

Summary: Returns the lowest-scoring members from a sorted set after removing them. Deletes the sorted set if the last member was popped.

Overview

Removes and returns up to `count` members with the lowest scores in the sorted
set stored at `key`.

When left unspecified, the default value for `count` is 1. Specifying a `count`
value that is higher than the sorted set's cardinality will not produce an
error. When returning multiple elements, the one with the lowest score will
be the first, followed by the elements with greater scores.

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"
ZPOPMIN myzset

Return information


ZRANDMEMBER

Summary: Returns one or more random members from a sorted set.

Overview

When called with just the `key` argument, return a random element from the sorted set value stored at `key`.

If the provided `count` argument is positive, return an array of **distinct elements**.
The array's length is either `count` or the sorted set's cardinality ([`ZCARD`]()), whichever is lower.

If called with a negative `count`, the behavior changes and the command is allowed to return the **same element multiple times**.
In this case, the number of returned elements is the absolute value of the specified `count`.

The optional `WITHSCORES` modifier changes the reply so it includes the respective scores of the randomly selected elements from the sorted set.

Examples

ZADD dadi 1 uno 2 due 3 tre 4 quattro 5 cinque 6 sei
ZRANDMEMBER dadi
ZRANDMEMBER dadi
ZRANDMEMBER dadi -5 WITHSCORES

Specification of the behavior when count is passed

When the `count` argument is a positive value this command behaves as follows:

* No repeated elements are returned.
* If `count` is bigger than the cardinality of the sorted set, the command will only return the whole sorted set without additional elements.
* The order of elements in the reply is not truly random, so it is up to the client to shuffle them if needed.

When the `count` is a negative value, the behavior changes as follows:

* Repeating elements are possible.
* Exactly `count` elements, or an empty array if the sorted set is empty (non-existing key), are always returned.
* The order of elements in the reply is truly random.

| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

Return information

**RESP2:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): without the additional _count_ argument, the command returns a randomly selected member, or [Nil reply](../../develop/reference/protocol-spec#bulk-strings) when _key_ doesn't exist.
[Array reply](../../develop/reference/protocol-spec#arrays): when the additional _count_ argument is passed, the command returns an array of members, or an empty array when _key_ doesn't exist. If the _WITHSCORES_ modifier is used, the reply is a list of members and their scores from the sorted set.

**RESP3:**

[Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): without the additional _count_ argument, the command returns a randomly selected member, or [Null reply](../../develop/reference/protocol-spec#nulls) when _key_ doesn't exist.
[Array reply](../../develop/reference/protocol-spec#arrays): when the additional _count_ argument is passed, the command returns an array of members, or an empty array when _key_ doesn't exist. If the _WITHSCORES_ modifier is used, the reply is a list of members and their scores from the sorted set.


ZRANGE

Summary: Returns members in a sorted set within a range of indexes.

Common behavior and options

The order of elements is from the lowest to the highest score. Elements with the same score are ordered lexicographically.

The optional `REV` argument reverses the ordering, so elements are ordered from highest to lowest score, and score ties are resolved by reverse lexicographical ordering.

The optional `LIMIT` argument can be used to obtain a sub-range from the matching elements (similar to _SELECT LIMIT offset, count_ in SQL).
A negative `<count>` returns all elements from the `<offset>`. Keep in mind that if `<offset>` is large, the sorted set needs to be traversed for `<offset>` elements before getting to the elements to return, which can add up to O(N) time complexity.

The optional `WITHSCORES` argument supplements the command's reply with the scores of elements returned. The returned list contains `value1,score1,...,valueN,scoreN` instead of `value1,...,valueN`. Client libraries are free to return a more appropriate data type (suggestion: an array with (value, score) arrays/tuples).

Index ranges

By default, the command performs an index range query. The `<start>` and `<stop>` arguments represent zero-based indexes, where `0` is the first element, `1` is the next element, and so on. These arguments specify an **inclusive range**, so for example, `ZRANGE myzset 0 1` will return both the first and the second element of the sorted set.

The indexes can also be negative numbers indicating offsets from the end of the sorted set, with `-1` being the last element of the sorted set, `-2` the penultimate element, and so on.

Out of range indexes do not produce an error.

If `<start>` is greater than either the end index of the sorted set or `<stop>`, an empty list is returned.

If `<stop>` is greater than the end index of the sorted set, Redis will use the last element of the sorted set.

Score ranges

When the `BYSCORE` option is provided, the command behaves like [`ZRANGEBYSCORE`]() and returns the range of elements from the sorted set having scores equal or between `<start>` and `<stop>`.

`<start>` and `<stop>` can be `-inf` and `+inf`, denoting the negative and positive infinities, respectively. This means that you are not required to know the highest or lowest score in the sorted set to get all elements from or up to a certain score.

By default, the score intervals specified by `<start>` and `<stop>` are closed (inclusive).
It is possible to specify an open interval (exclusive) by prefixing the score
with the character `(`.

For example:

[code example]

Will return all elements with `1 < score <= 5` while:

[code example]

Will return all the elements with `5 < score < 10` (5 and 10 excluded).

Reverse ranges

Using the `REV` option reverses the sorted set, with index 0 as the element with the highest score.

By default, `<start>` must be less than or equal to `<stop>` to return anything.
However, if the `BYSCORE`, or `BYLEX` options are selected, the `<start>` is the highest score to consider, and `<stop>` is the lowest score to consider, therefore `<start>` must be greater than or equal to `<stop>` in order to return anything.

For example:

[code example]

Will return the elements between index 5 and 10 in the reversed index.

[code example]

Will return all elements with scores less than 10 and greater than 5.

Lexicographical ranges

When the `BYLEX` option is used, the command behaves like [`ZRANGEBYLEX`]() and returns the range of elements from the sorted set between the `<start>` and `<stop>` lexicographical closed range intervals.

Note that lexicographical ordering relies on all elements having the same score. The reply is unspecified when the elements have different scores.

Valid `<start>` and `<stop>` must start with `(` or `[`, in order to specify
whether the range interval is exclusive or inclusive, respectively.

The special values of `+` or `-` for `<start>` and `<stop>` mean positive and negative infinite strings, respectively, so for instance the command `ZRANGE myzset - + BYLEX` is guaranteed to return all the elements in the sorted set, providing that all the elements have the same score.

The `REV` options reverses the order of the `<start>` and `<stop>` elements, where `<start>` must be lexicographically greater than `<stop>` to produce a non-empty result.

Lexicographical comparison of strings

Strings are compared as a binary array of bytes. Because of how the ASCII character set is specified, this means that usually this also have the effect of comparing normal ASCII characters in an obvious dictionary way. However, this is not true if non-plain ASCII strings are used (for example, utf8 strings).

However, the user can apply a transformation to the encoded string so that the first part of the element inserted in the sorted set will compare as the user requires for the specific application. For example, if I want to
add strings that will be compared in a case-insensitive way, but I still
want to retrieve the real case when querying, I can add strings in the
following way:

    ZADD autocomplete 0 foo:Foo 0 bar:BAR 0 zap:zap

Because of the first *normalized* part in every element (before the colon character), we are forcing a given comparison. However, after the range is queried using `ZRANGE ... BYLEX`, the application can display to the user the second part of the string, after the colon.

The binary nature of the comparison allows to use sorted sets as a general purpose index, for example, the first part of the element can be a 64-bit big-endian number. Since big-endian numbers have the most significant bytes in the initial positions, the binary comparison will match the numerical comparison of the numbers. This can be used in order to implement range queries on 64-bit values. As in the example below, after the first 8 bytes, we can store the value of the element we are indexing.

Examples

#### Code Examples

Foundational: Retrieve a range of members from a sorted set by index using ZRANGE (supports negative indexes, inclusive range)

**Difficulty:** Beginner

**Commands:** ZADD, ZRANGE

**Complexity:**
- ZADD: O(log(N)
- ZRANGE: O(log(N)

**Redis CLI:**

[code example]

**Available in:** Redis CLI, C# (Synchronous), Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python

**C# (Synchronous):**

[code example]

**Go:**

[code example]

**Java (Synchronous - Jedis):**

[code example]

**JavaScript (Node.js):**

[code example]

**Python:**

[code example]

The following example using `WITHSCORES` shows how the command returns always an array, but this time, populated with *element_1*, *score_1*, *element_2*, *score_2*, ..., *element_N*, *score_N*.

#### Code Examples

Return scores with members: Retrieve members with their scores from a sorted set using ZRANGE with WITHSCORES option

**Difficulty:** Intermediate

**Commands:** ZADD, ZRANGE

**Complexity:**
- ZADD: O(log(N)
- ZRANGE: O(log(N)

**Redis CLI:**

[code example]

**Available in:** Redis CLI, C# (Synchronous), Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python

**C# (Synchronous):**

[code example]

**Go:**

[code example]

**Java (Synchronous - Jedis):**

[code example]

**JavaScript (Node.js):**

[code example]

**Python:**

[code example]

This example shows how to query the sorted set by score, excluding the value `1` and up to infinity, returning only the second element of the result:

#### Code Examples

Query by score: Query a sorted set by score range using ZRANGE with BYSCORE and LIMIT options (supports exclusive ranges and pagination)

**Difficulty:** Intermediate

**Commands:** ZADD, ZRANGE

**Complexity:**
- ZADD: O(log(N)
- ZRANGE: O(log(N)

**Redis CLI:**

[code example]

**Available in:** Redis CLI, C# (Synchronous), Go, Java (Synchronous - Jedis), JavaScript (Node.js), Python

**C# (Synchronous):**

[code example]

**Go:**

[code example]

**Java (Synchronous - Jedis):**

[code example]

**JavaScript (Node.js):**

[code example]

**Python:**

[code example]

Give these commands a try in the interactive console:

ZADD myzset 1 "one" 2 "two" 3 "three"
ZRANGE myzset 0 -1
ZRANGE myzset 2 3
ZRANGE myzset -2 -1

Return information

**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of members in the specified range with, optionally, their scores when the _WITHSCORES_ option is given.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of members in the specified range with, optionally, their scores when the _WITHSCORES_ option is given.

> ZADD myzset 1 "one" 2 "two" 3 "three"
(integer) 3
> ZRANGE myzset 0 -1
1) "one"
2) "two"
3) "three"
> ZRANGE myzset 2 3
1) "three"
> ZRANGE myzset -2 -1
1) "two"
2) "three"

long zRangeResult1 = db.SortedSetAdd(
            "myzset",
            [
                new("one", 1),
                new("two", 2),
                new("three", 3)
            ]
        );
        Console.WriteLine(zRangeResult1);   // >>> 3

        RedisValue[] zRangeResult2 = db.SortedSetRangeByRank("myzset", 0, -1);
        Console.WriteLine(string.Join(", ", zRangeResult2));
        // >>> one, two, three

        RedisValue[] zRangeResult3 = db.SortedSetRangeByRank("myzset", 2, 3);
        Console.WriteLine(string.Join(", ", zRangeResult3));
        // >>> three

        RedisValue[] zRangeResult4 = db.SortedSetRangeByRank("myzset", -2, -1);
        Console.WriteLine(string.Join(", ", zRangeResult4));
        // >>> two, three

zrangeResult1, err := rdb.ZAdd(ctx, "myzset",
		redis.Z{Member: "one", Score: 1},
		redis.Z{Member: "two", Score: 2},
		redis.Z{Member: "three", Score: 3},
	).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zrangeResult1) // >>> 3

	zrangeResult2, err := rdb.ZRange(ctx, "myzset", 0, -1).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zrangeResult2) // >>> [one two three]

	zrangeResult3, err := rdb.ZRange(ctx, "myzset", 2, 3).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zrangeResult3) // >>> [three]

	zrangeResult4, err := rdb.ZRange(ctx, "myzset", -2, -1).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zrangeResult4) // >>> [two three]

Map<String, Double> zRangeExampleParams1 = new HashMap<>();
        zRangeExampleParams1.put("one", 1.0);
        zRangeExampleParams1.put("two", 2.0);
        zRangeExampleParams1.put("three", 3.0);
        long zRangeResult1 = jedis.zadd("myzset", zRangeExampleParams1);
        System.out.println(zRangeResult1);  // >>> 3

        List<String> zRangeResult2 = jedis.zrange("myzset", new ZRangeParams(0, -1));
        System.out.println(String.join(", ", zRangeResult2));   // >>> one, two, three

        List<String> zRangeResult3 = jedis.zrange("myzset", new ZRangeParams(2, 3));
        System.out.println(String.join(", ", zRangeResult3));   // >> three

        List<String> zRangeResult4 = jedis.zrange("myzset", new ZRangeParams(-2, -1));
        System.out.println(String.join(", ", zRangeResult4));   // >> two, three

const val5 = await client.zAdd("myzset", [
  { value: 'one', score: 1 },
  { value: 'two', score: 2 },
  { value: 'three', score: 3 }
]);
console.log(val5);
// returns 3

const val6 = await client.zRange('myzset', 0, -1);
console.log(val6);
// returns ['one', 'two', 'three']

const val7 = await client.zRange('myzset', 2, 3);
console.log(val7);
// returns ['three']

const val8 = await client.zRange('myzset', -2, -1);
console.log(val8);
// returns ['two', 'three']

res = r.zadd("myzset", {"one": 1, "two":2, "three":3})
print(res)
# >>> 3

res = r.zrange("myzset", 0, -1)
print(res)
# >>> ['one', 'two', 'three']

res = r.zrange("myzset", 2, 3)
print(res)
# >>> ['three']

res = r.zrange("myzset", -2, -1)
print(res)
# >>> ['two', 'three']

> ZADD myzset 1 "one" 2 "two" 3 "three"
(integer) 3
> ZRANGE myzset 0 1 WITHSCORES
1) "one"
2) "1"
3) "two"
4) "2"

long zRangeResult5 = db.SortedSetAdd(
            "myzset",
            [
                new("one", 1),
                new("two", 2),
                new("three", 3)
            ]
        );

        SortedSetEntry[] zRangeResult6 = db.SortedSetRangeByRankWithScores("myzset", 0, 1);
        Console.WriteLine($"{string.Join(", ", zRangeResult6.Select(b => $"{b.Element}: {b.Score}"))}");
        // >>> one: 1, two: 2

zRangeResult5, err := rdb.ZAdd(ctx, "myzset",
		redis.Z{Member: "one", Score: 1},
		redis.Z{Member: "two", Score: 2},
		redis.Z{Member: "three", Score: 3},
	).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zRangeResult5) // >>> 3

	zRangeResult6, err := rdb.ZRangeWithScores(ctx, "myzset", 0, 1).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zRangeResult6) // >>> [{1 one} {2 two}]

Map<String, Double> zRangeExampleParams2 = new HashMap<>();
        zRangeExampleParams2.put("one", 1.0);
        zRangeExampleParams2.put("two", 2.0);
        zRangeExampleParams2.put("three", 3.0);
        long zRangeResult5 = jedis.zadd("myzset", zRangeExampleParams2);
        System.out.println(zRangeResult5);  // >>> 3

        List<Tuple> zRangeResult6 = jedis.zrangeWithScores("myzset", new ZRangeParams(0, 1));

        for (Tuple item: zRangeResult6) {
            System.out.println("Element: " + item.getElement() + ", Score: " + item.getScore());
        }
        // >>> Element: one, Score: 1.0
        // >>> Element: two, Score: 2.0

const val9 = await client.zAdd("myzset", [
  { value: 'one', score: 1 },
  { value: 'two', score: 2 },
  { value: 'three', score: 3 }
]);
console.log(val9);
// returns 3

const val10 = await client.zRangeWithScores('myzset', 0, 1);
console.log(val10);
// returns [{value: 'one', score: 1}, {value: 'two', score: 2}]

res = r.zadd("myzset", {"one": 1, "two":2, "three":3})
res = r.zrange("myzset", 0, 1, withscores=True)
print(res)
# >>> [('one', 1.0), ('two', 2.0)]

> ZADD myzset 1 "one" 2 "two" 3 "three"
(integer) 3
> ZRANGE myzset (1 +inf BYSCORE LIMIT 1 1
1) "three"

long zRangeResult7 = db.SortedSetAdd(
            "myzset",
            [
                new("one", 1),
                new("two", 2),
                new("three", 3)
            ]
        );

        RedisValue[] zRangeResult8 = db.SortedSetRangeByScore(
            "myzset",
            1,
            double.PositiveInfinity,
            Exclude.Start,
            skip: 1, take: 1
        );
        Console.WriteLine(string.Join(", ", zRangeResult8));
        // >>> three

zRangeResult7, err := rdb.ZAdd(ctx, "myzset",
		redis.Z{Member: "one", Score: 1},
		redis.Z{Member: "two", Score: 2},
		redis.Z{Member: "three", Score: 3},
	).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zRangeResult7) // >>> 3

	zRangeResult8, err := rdb.ZRangeArgs(ctx,
		redis.ZRangeArgs{
			Key:     "myzset",
			ByScore: true,
			Start:   "(1",
			Stop:    "+inf",
			Offset:  1,
			Count:   1,
		},
	).Result()

	if err != nil {
		panic(err)
	}

	fmt.Println(zRangeResult8) // >>> [three]

Map<String, Double> zRangeExampleParams3 = new HashMap<>();
        zRangeExampleParams3.put("one", 1.0);
        zRangeExampleParams3.put("two", 2.0);
        zRangeExampleParams3.put("three", 3.0);
        long zRangeResult7 = jedis.zadd("myzset", zRangeExampleParams3);
        System.out.println(zRangeResult7);  // >>> 3

        List<String> zRangeResult8 = jedis.zrangeByScore("myzset", "(1", "+inf", 1, 1);
        System.out.println(String.join(", ", zRangeResult8));   // >>> three

const val11 = await client.zAdd("myzset", [
  { value: 'one', score: 1 },
  { value: 'two', score: 2 },
  { value: 'three', score: 3 }
]);
console.log(val11);
// returns 3

const val12 = await client.zRange('myzset', 2, 3, { BY: 'SCORE', LIMIT: { offset: 1, count: 1 } });
console.log(val12);
// >>> ['three']

res = r.zadd("myzset", {"one": 1, "two":2, "three":3})
res = r.zrange("myzset", 2, 3, byscore=True, offset=1, num=1)
print(res)
# >>> ['three']


ZRANGEBYLEX

Summary: Returns members in a sorted set within a lexicographical range.

Overview

When all the elements in a sorted set are inserted with the same score, in order to force lexicographical ordering, this command returns all the elements in the sorted set at `key` with a value between `min` and `max`.

If the elements in the sorted set have different scores, the returned elements are unspecified.

The elements are considered to be ordered from lower to higher strings as compared byte-by-byte using the `memcmp()` C function. Longer strings are considered greater than shorter strings if the common part is identical.

The optional `LIMIT` argument can be used to only get a range of the matching
elements (similar to _SELECT LIMIT offset, count_ in SQL). A negative `count`
returns all elements from the `offset`.
Keep in mind that if `offset` is large, the sorted set needs to be traversed for
`offset` elements before getting to the elements to return, which can add up to
O(N) time complexity.

How to specify intervals

Valid *start* and *stop* must start with `(` or `[`, in order to specify
if the range item is respectively exclusive or inclusive.
The special values of `+` or `-` for *start* and *stop* have the special
meaning or positively infinite and negatively infinite strings, so for
instance the command **ZRANGEBYLEX myzset - +** is guaranteed to return
all the elements in the sorted set, if all the elements have the same
score.

Details on strings comparison

Strings are compared as binary array of bytes. Because of how the ASCII character
set is specified, this means that usually this also have the effect of comparing
normal ASCII characters in an obvious dictionary way. However this is not true
if non plain ASCII strings are used (for example utf8 strings).

However the user can apply a transformation to the encoded string so that
the first part of the element inserted in the sorted set will compare as the
user requires for the specific application. For example if I want to
add strings that will be compared in a case-insensitive way, but I still
want to retrieve the real case when querying, I can add strings in the
following way:

    ZADD autocomplete 0 foo:Foo 0 bar:BAR 0 zap:zap

Because of the first *normalized* part in every element (before the colon character), we are forcing a given comparison, however after the range is queries using `ZRANGEBYLEX` the application can display to the user the second part of the string, after the colon.

The binary nature of the comparison allows to use sorted sets as a general
purpose index, for example the first part of the element can be a 64 bit
big endian number: since big endian numbers have the most significant bytes
in the initial positions, the binary comparison will match the numerical
comparison of the numbers. This can be used in order to implement range
queries on 64 bit values. As in the example below, after the first 8 bytes
we can store the value of the element we are actually indexing.

Examples

ZADD myzset 0 a 0 b 0 c 0 d 0 e 0 f 0 g
ZRANGEBYLEX myzset - [c
ZRANGEBYLEX myzset - (c
ZRANGEBYLEX myzset [aaa (g

| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> | Deprecated as of Redis v6.2.0. |

Return information

**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of elements in the specified score range.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of elements in the specified score range.


ZRANGEBYSCORE

Summary: Returns members in a sorted set within a range of scores.

Overview

Returns all the elements in the sorted set at `key` with a score between `min`
and `max` (including elements with score equal to `min` or `max`).
The elements are considered to be ordered from low to high scores.

The elements having the same score are returned in lexicographical order (this
follows from a property of the sorted set implementation in Redis and does not
involve further computation).

The optional `LIMIT` argument can be used to only get a range of the matching
elements (similar to _SELECT LIMIT offset, count_ in SQL). A negative `count`
returns all elements from the `offset`.
Keep in mind that if `offset` is large, the sorted set needs to be traversed for
`offset` elements before getting to the elements to return, which can add up to
O(N) time complexity.

The optional `WITHSCORES` argument makes the command return both the element and
its score, instead of the element alone.
This option is available since Redis 2.0.

Exclusive intervals and infinity

`min` and `max` can be `-inf` and `+inf`, so that you are not required to know
the highest or lowest score in the sorted set to get all elements from or up to
a certain score.

By default, the interval specified by `min` and `max` is closed (inclusive).
It is possible to specify an open interval (exclusive) by prefixing the score
with the character `(`.
For example:

[code example]

Will return all elements with `1 < score <= 5` while:

[code example]

Will return all the elements with `5 < score < 10` (5 and 10 excluded).

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"
ZRANGEBYSCORE myzset -inf +inf
ZRANGEBYSCORE myzset 1 2
ZRANGEBYSCORE myzset (1 2
ZRANGEBYSCORE myzset (1 (2

Pattern: weighted random selection of an element

Normally `ZRANGEBYSCORE` is simply used in order to get range of items
where the score is the indexed integer key, however it is possible to do less
obvious things with the command.

For example a common problem when implementing Markov chains and other algorithms
is to select an element at random from a set, but different elements may have
different weights that change how likely it is they are picked.

This is how we use this command in order to mount such an algorithm:

Imagine you have elements A, B and C with weights 1, 2 and 3.
You compute the sum of the weights, which is 1+2+3 = 6

At this point you add all the elements into a sorted set using this algorithm:

[code example]

This means that you set:

[code example]

Since this involves approximations, in order to avoid C is set to,
like, 0.998 instead of 1, we just modify the above algorithm to make sure
the last score is 1 (left as an exercise for the reader...).

At this point, each time you want to get a weighted random element,
just compute a random number between 0 and 1 (which is like calling
`rand()` in most languages), so you can just do:

    RANDOM_ELE = ZRANGEBYSCORE key RAND() +inf LIMIT 0 1

Return information

**RESP2:**

* [Array reply](../../develop/reference/protocol-spec#arrays): a list of the members with, optionally, their scores in the specified score range.

**RESP3:**

* [Array reply](../../develop/reference/protocol-spec#arrays): a list of the members with, optionally, their scores in the specified score range.

SUM = ELEMENTS.TOTAL_WEIGHT // 6 in this case.
SCORE = 0
FOREACH ELE in ELEMENTS
    SCORE += ELE.weight / SUM
    ZADD KEY SCORE ELE
END

A to score 0.16
B to score .5
C to score 1


ZRANGESTORE

Summary: Stores a range of members from sorted set in a key.

Overview

This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

This command is like [`ZRANGE`](), but stores the result in the `<dst>` destination key.

Examples

ZADD srczset 1 "one" 2 "two" 3 "three" 4 "four"
ZRANGESTORE dstzset srczset 2 -1
ZRANGE dstzset 0 -1

| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

Return information

**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of elements in the resulting sorted set.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of elements in the resulting sorted set.


ZRANK

Summary: Returns the index of a member in a sorted set ordered by ascending scores.

Overview

Returns the rank of `member` in the sorted set stored at `key`, with the scores
ordered from low to high.
The rank (or index) is 0-based, which means that the member with the lowest
score has rank `0`.

The optional `WITHSCORE` argument supplements the command's reply with the score of the element returned.

Use [`ZREVRANK`]() to get the rank of an element with the scores ordered from high
to low.

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"
ZRANK myzset "three"
ZRANK myzset "four"
ZRANK myzset "three" WITHSCORE
ZRANK myzset "four" WITHSCORE

Return information

**RESP2:**

One of the following:
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if the key does not exist or the member does not exist in the sorted set.
* [Integer reply](../../develop/reference/protocol-spec#integers): the rank of the member when _WITHSCORE_ is not used.
* [Array reply](../../develop/reference/protocol-spec#arrays): the rank and score of the member when _WITHSCORE_ is used.

**RESP3:**

One of the following:
* [Null reply](../../develop/reference/protocol-spec#nulls): if the key does not exist or the member does not exist in the sorted set.
* [Integer reply](../../develop/reference/protocol-spec#integers): the rank of the member when _WITHSCORE_ is not used.
* [Array reply](../../develop/reference/protocol-spec#arrays): the rank and score of the member when _WITHSCORE_ is used.


ZREM

Summary: Removes one or more members from a sorted set. Deletes the sorted set if all members were removed.

Overview

Removes the specified members from the sorted set stored at `key`.
Non existing members are ignored.

An error is returned when `key` exists and does not hold a sorted set.

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"
ZREM myzset "two"
ZRANGE myzset 0 -1 WITHSCORES

Return information

**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members removed from the sorted set, not including non-existing members.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members removed from the sorted set, not including non-existing members.


ZREMRANGEBYLEX

Summary: Removes members in a sorted set within a lexicographical range. Deletes the sorted set if all members were removed.

Overview

When all the elements in a sorted set are inserted with the same score, in order to force lexicographical ordering, this command removes all elements in the sorted set stored at `key` between the lexicographical range specified by `min` and `max`.

The meaning of `min` and `max` are the same of the [`ZRANGEBYLEX`]() command. Similarly, this command actually removes the same elements that [`ZRANGEBYLEX`]() would return if called with the same `min` and `max` arguments.

Examples

ZADD myzset 0 aaaa 0 b 0 c 0 d 0 e
ZADD myzset 0 foo 0 zap 0 zip 0 ALPHA 0 alpha
ZRANGE myzset 0 -1
ZREMRANGEBYLEX myzset [alpha [omega
ZRANGE myzset 0 -1

Return information

**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of members removed.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): Number of members removed.


ZREMRANGEBYRANK

Summary: Removes members in a sorted set within a range of indexes. Deletes the sorted set if all members were removed.

Overview

Removes all elements in the sorted set stored at `key` with rank between `start`
and `stop`.
Both `start` and `stop` are `0` -based indexes with `0` being the element with
the lowest score.
These indexes can be negative numbers, where they indicate offsets starting at
the element with the highest score.
For example: `-1` is the element with the highest score, `-2` the element with
the second highest score and so forth.

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"
ZREMRANGEBYRANK myzset 0 1
ZRANGE myzset 0 -1 WITHSCORES

Return information


ZREMRANGEBYSCORE

Summary: Removes members in a sorted set within a range of scores. Deletes the sorted set if all members were removed.

Overview

Removes all elements in the sorted set stored at `key` with a score between
`min` and `max` (inclusive).

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"
ZREMRANGEBYSCORE myzset -inf (2
ZRANGE myzset 0 -1 WITHSCORES

Return information


ZREVRANGE

Summary: Returns members in a sorted set within a range of indexes in reverse order.

Overview

Returns the specified range of elements in the sorted set stored at `key`.
The elements are considered to be ordered from the highest to the lowest score.
Descending lexicographical order is used for elements with equal score.

Apart from the reversed ordering, `ZREVRANGE` is similar to [`ZRANGE`]().

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"
ZREVRANGE myzset 0 -1
ZREVRANGE myzset 2 3
ZREVRANGE myzset -2 -1

| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> | Deprecated as of Redis v6.2.0. |

Return information

**RESP2:**

* [Array reply](../../develop/reference/protocol-spec#arrays): a list of members in the specified range, optionally with their scores if _WITHSCORE_ was used.

**RESP3:**

* [Array reply](../../develop/reference/protocol-spec#arrays): a list of members in the specified range, optionally with their scores if _WITHSCORE_ was used.


ZREVRANGEBYLEX

Summary: Returns members in a sorted set within a lexicographical range in reverse order.

Overview

When all the elements in a sorted set are inserted with the same score, in order to force lexicographical ordering, this command returns all the elements in the sorted set at `key` with a value between `max` and `min`.

Apart from the reversed ordering, `ZREVRANGEBYLEX` is similar to [`ZRANGEBYLEX`]().

Examples

ZADD myzset 0 a 0 b 0 c 0 d 0 e 0 f 0 g
ZREVRANGEBYLEX myzset [c -
ZREVRANGEBYLEX myzset (c -
ZREVRANGEBYLEX myzset (g [aaa

Return information

**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): a list of members in the specified score range.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): List of the elements in the specified score range.


ZREVRANGEBYSCORE

Summary: Returns members in a sorted set within a range of scores in reverse order.

Overview

Returns all the elements in the sorted set at `key` with a score between `max`
and `min` (including elements with score equal to `max` or `min`).
In contrary to the default ordering of sorted sets, for this command the
elements are considered to be ordered from high to low scores.

The elements having the same score are returned in reverse lexicographical
order.

Apart from the reversed ordering, `ZREVRANGEBYSCORE` is similar to
[`ZRANGEBYSCORE`]().

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"
ZREVRANGEBYSCORE myzset +inf -inf
ZREVRANGEBYSCORE myzset 2 1
ZREVRANGEBYSCORE myzset 2 (1
ZREVRANGEBYSCORE myzset (2 (1

Return information

**RESP2:**

* [Array reply](../../develop/reference/protocol-spec#arrays): a list of the members and, optionally, their scores in the specified score range.

**RESP3:**

* [Array reply](../../develop/reference/protocol-spec#arrays): a list of the members and, optionally, their scores in the specified score range.


ZREVRANK

Summary: Returns the index of a member in a sorted set ordered by descending scores.

Overview

Returns the rank of `member` in the sorted set stored at `key`, with the scores
ordered from high to low.
The rank (or index) is 0-based, which means that the member with the highest
score has rank `0`.

The optional `WITHSCORE` argument supplements the command's reply with the score of the element returned.

Use [`ZRANK`]() to get the rank of an element with the scores ordered from low to
high.

Examples

ZADD myzset 1 "one"
ZADD myzset 2 "two"
ZADD myzset 3 "three"
ZREVRANK myzset "one"
ZREVRANK myzset "four"
ZREVRANK myzset "three" WITHSCORE
ZREVRANK myzset "four" WITHSCORE

| Redis
Software | Redis
Cloud | Notes |
|:----------------------|:-----------------|:------|
| ✅ Standard
<nobr>✅ Active-Active</nobr> | ✅ Standard
<nobr>✅ Active-Active</nobr> |  |

Return information

**RESP2:**

One of the following:
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if the key does not exist or the member does not exist in the sorted set.
* [Integer reply](../../develop/reference/protocol-spec#integers): The rank of the member when _WITHSCORE_ is not used.
* [Array reply](../../develop/reference/protocol-spec#arrays): The rank and score of the member when _WITHSCORE_ is used.

**RESP3:**

One of the following:
* [Null reply](../../develop/reference/protocol-spec#nulls): if the key does not exist or the member does not exist in the sorted set.
* [Integer reply](../../develop/reference/protocol-spec#integers): The rank of the member when _WITHSCORE_ is not used.
* [Array reply](../../develop/reference/protocol-spec#arrays): The rank and score of the member when _WITHSCORE_ is used.


ZSCAN

Summary: Iterates over members and scores of a sorted set.

Overview

See [`SCAN`]() for `ZSCAN` documentation.

Return information

**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): cursor and scan response in array form.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): cursor and scan response in array form.


ZSCORE

Summary: Returns the score of a member in a sorted set.

Overview

Returns the score of `member` in the sorted set at `key`.

If `member` does not exist in the sorted set, or `key` does not exist, `nil` is
returned.

Examples

ZADD myzset 1 "one"
ZSCORE myzset "one"

Return information

**RESP2:**

One of the following:
* [Bulk string reply](../../develop/reference/protocol-spec#bulk-strings): the score of the member (a double-precision floating point number), represented as a string.
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if _member_ does not exist in the sorted set, or the key does not exist.

**RESP3:**

One of the following:
* [Double reply](../../develop/reference/protocol-spec#doubles): the score of the member (a double-precision floating point number).
* [Nil reply](../../develop/reference/protocol-spec#bulk-strings): if _member_ does not exist in the sorted set, or the key does not exist.


ZUNION

Summary: Returns the union of multiple sorted sets.

Overview

This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

This command is similar to [`ZUNIONSTORE`](), but instead of storing the resulting
sorted set, it is returned to the client.

For a description of the `WEIGHTS` and `AGGREGATE` options, see [`ZUNIONSTORE`]().

Examples

ZADD zset1 1 "one"
ZADD zset1 2 "two"
ZADD zset2 1 "one"
ZADD zset2 2 "two"
ZADD zset2 3 "three"
ZUNION 2 zset1 zset2
ZUNION 2 zset1 zset2 WITHSCORES

Return information

**RESP2:**

[Array reply](../../develop/reference/protocol-spec#arrays): the result of the union with, optionally, their scores when _WITHSCORES_ is used.

**RESP3:**

[Array reply](../../develop/reference/protocol-spec#arrays): the result of the union with, optionally, their scores when _WITHSCORES_ is used.


ZUNIONSTORE

Summary: Stores the union of multiple sorted sets in a key.

Overview

This command's behavior varies in clustered Redis environments. See the [multi-key operations]() page for more information.

Computes the union of `numkeys` sorted sets given by the specified keys, and
stores the result in `destination`.
It is mandatory to provide the number of input keys (`numkeys`) before passing
the input keys and the other (optional) arguments.

By default, the resulting score of an element is the sum of its scores in the
sorted sets where it exists.

Using the `WEIGHTS` option, it is possible to specify a multiplication factor
for each input sorted set.
This means that the score of every element in every input sorted set is
multiplied by this factor before being passed to the aggregation function.
When `WEIGHTS` is not given, the multiplication factors default to `1`.

With the `AGGREGATE` option, it is possible to specify how the results of the
union are aggregated.
This option defaults to `SUM`, where the score of an element is summed across
the inputs where it exists.
When this option is set to either `MIN` or `MAX`, the resulting set will contain
the minimum or maximum score of an element across the inputs where it exists.

If `destination` already exists, it is overwritten.

Examples

ZADD zset1 1 "one"
ZADD zset1 2 "two"
ZADD zset2 1 "one"
ZADD zset2 2 "two"
ZADD zset2 3 "three"
ZUNIONSTORE out 2 zset1 zset2 WEIGHTS 2 3
ZRANGE out 0 -1 WITHSCORES

Return information

**RESP2:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of elements in the resulting sorted set.

**RESP3:**

[Integer reply](../../develop/reference/protocol-spec#integers): the number of elements in the resulting sorted set.


How agents work

Summary: Learn how AI agents work and why Redis is the perfect foundation for building intelligent systems

How AI agents work

AI agents are autonomous systems that go far beyond simple chatbots. They combine large language models (LLMs) with external tools, memory, and planning capabilities to accomplish complex tasks.

**Key differences from chatbots:**
- Maintain state across multiple conversations
- Reason through problems step-by-step
- Take actions in the real world
- Learn and adapt from interactions

Core agent architecture

The agent processing cycle

Every user interaction follows a 6-step cycle that makes agents intelligent:

Why this cycle matters:
- Maintains context across multiple conversations
- Learns from experience to improve future responses
- Handles complex tasks that require multiple steps
- Recovers from failures and adapts plans in real-time

> Example: When you ask "Book me a flight to Paris and find a hotel," the agent breaks this into separate tasks, remembers your travel preferences, searches for options, and coordinates the booking process.

Why Redis powers AI agents

Redis is the **ideal foundation** for AI agents because it excels at the three things agents need most: **speed**, **memory**, and **search**.

Redis powers every part of your agent

Planner

Stores workflow templates and agent plans as Hashes or JSON. Enables complex multi-step reasoning.

Retriever

Vector Search finds semantically similar documents instantly. Supports hybrid search for better results.

Executor

Stores conversation history, user preferences, and intermediate results. Maintains state across workflows.

Key advantages

**Ultra-fast response times**
- Sub-millisecond data access keeps conversations flowing naturally
- In-memory processing eliminates disk I/O bottlenecks
- Optimized data structures for different use cases

**Built-in vector search**
- Native vector indexing with HNSW, FLAT, and SVS-VAMANA algorithms
- SVS-VAMANA leverages Intel hardware acceleration for enhanced performance
- Hybrid search combining vector similarity with metadata filtering
- Real-time updates without index rebuilds
- [Learn more about Redis Vector Search →]()

**Agent memory**
- **Short-term**: Conversation context and session state
- **Long-term**: User preferences and learned patterns
- Flexible data structures (Hashes, Lists, Streams, JSON) for different memory types
- [Explore Redis data structures →](/develop/data-types/)

Types of agents you can build

Conversational assistants

Build chatbots and virtual assistants that:
- Maintain natural conversations with context and memory
- Handle multiple topics within a single conversation
- Provide personalized responses based on user history
- Escalate to human agents when needed

[Build a conversational agent →](../)

Recommendation engines

Create intelligent recommendation systems that:
- Learn from user behavior and preferences
- Provide real-time personalized suggestions
- Handle both explicit feedback (ratings) and implicit signals (clicks, time spent)
- Scale to millions of users and items

[Build a recommendation agent →](../)

Task automation agents

Automate complex workflows and business processes:
- Execute multi-step tasks with decision-making
- Integrate with APIs and external systems
- Handle error recovery and retry logic
- Monitor and report on task completion

Data analysis agents

Process and analyze large datasets intelligently:
- Perform statistical analysis and pattern recognition
- Generate insights and reports automatically
- Handle real-time data streams
- Create visualizations and dashboards

Content generation agents

Create and manage content at scale:
- Generate articles, summaries, and documentation
- Adapt content for different audiences and formats
- Maintain brand voice and style consistency
- Handle content moderation and quality control

Customer support agents

Provide intelligent customer service:
- Answer questions using knowledge bases
- Route complex issues to human agents
- Track customer satisfaction and feedback
- Learn from interactions to improve responses

Research and retrieval agents

Find and synthesize information from multiple sources:
- Search across documents, databases, and web content
- Summarize findings and extract key insights
- Fact-check and verify information accuracy
- Maintain up-to-date knowledge repositories

Monitoring and alerting agents

Watch systems and notify when action is needed:
- Monitor application performance and health
- Detect anomalies and security threats
- Send intelligent alerts with context
- Suggest remediation actions

Personal productivity agents

Help users manage tasks and information:
- Schedule meetings and manage calendars
- Organize and prioritize tasks
- Provide reminders and follow-ups
- Learn user preferences and habits

Trading and financial agents

Make intelligent financial decisions:
- Analyze market data and trends
- Execute trades based on predefined strategies
- Manage risk and portfolio optimization
- Generate financial reports and insights

Agent architecture patterns

Single-agent systems

Simple agents that handle all tasks within one system:
- Easier to develop and maintain
- Good for focused use cases
- All logic contained in one place
- Suitable for most applications

Multi-agent systems

Multiple specialized agents working together:
- Each agent handles specific domains or tasks
- agents can communicate and coordinate
- More complex but more scalable
- Good for enterprise applications

Hierarchical agents

Agents organized in layers with different responsibilities:
- High-level agents handle planning and coordination
- Low-level agents execute specific tasks
- Clear separation of concerns
- Easier to debug and maintain

Redis data structures for agent memory

Understanding how to map agent memory needs to Redis data structures is crucial for building efficient agents:

Redis streams for conversation history

- Use case: Ordered conversation logs with timestamps and metadata
- Key benefits: Automatic ordering, range queries, consumer groups, guaranteed delivery
- Implementation: Store user/agent message pairs with rich contextual metadata
- Retention: Use XTRIM for automatic cleanup based on age or count limits
- [Learn about Redis Streams →](/develop/data-types/streams/)

Redis Hashes for User Profiles

- Use case: Structured user data with frequent partial updates and atomic operations
- Key benefits: Memory efficient field-level operations, atomic updates, O(1) field access
- Implementation: Multi-layered profile system with preferences, behavior patterns, and learned data
- Scaling: Hash tags for cluster distribution, field expiration for data lifecycle management
- [Learn about Redis Hashes →](/develop/data-types/hashes/)

Redis JSON for Complex State

- Use case: Nested data structures, complex agent workflows, hierarchical configurations
- Key benefits: JSONPath queries, atomic nested updates, schema validation, efficient storage
- Implementation: Multi-step task orchestration, complex decision trees, dynamic configurations
- Querying: Advanced JSONPath expressions for complex data retrieval and manipulation
- [Learn about Redis JSON →](/develop/data-types/json/)

Redis Sets for Relationships and Tags

- Use case: Entity relationships, user interest tracking, session management, feature flags
- Key benefits: O(1) membership testing, efficient set operations, automatic deduplication
- Implementation: Complex relationship modeling, real-time recommendation engines, access control
- Operations: Union, intersection, difference for advanced analytics and personalization
- [Learn about Redis Sets →](/develop/data-types/sets/)

Redis Vector Sets for Semantic Search

- Use case: Embedding storage, similarity search, semantic retrieval, content recommendations
- Key benefits: High-performance vector similarity search, multiple distance metrics, real-time indexing
- Implementation: RAG systems, semantic memory, content discovery, personalized recommendations
- Queries: K-nearest neighbor search, range queries, hybrid filtering with metadata
- [Learn about Redis Vector Sets →]()

Redis Sorted Sets for Rankings and Priorities

- Use case: Dynamic scoring systems, priority queues, leaderboards, time-series data
- Key benefits: O(log N) insertions, range queries by score/rank, atomic score updates
- Implementation: Real-time recommendation scoring, task prioritization, performance analytics
- Queries: Range by score, rank, lexicographical order, and complex aggregations
- [Learn about Redis Sorted Sets →](/develop/data-types/sorted-sets/)

Reliability features

Production-ready agents include built-in reliability features:

Error handling

- Gracefully handle API failures and unexpected inputs
- Provide helpful error messages when things go wrong
- Continue functioning even when some components fail

Retry logic

- Automatically retry failed operations with exponential backoff
- Handle temporary network issues and rate limiting
- Ensure important operations complete successfully

Logging and monitoring

- Track what your agent does for debugging and improvement
- Monitor performance metrics like response times
- Log errors and unusual behavior for investigation

Performance optimization

- Cache frequently accessed information
- Use efficient data structures for fast retrieval
- Scale resources based on demand

Production deployment considerations

Monitoring and Observability

- Agent performance metrics: Response times, success rates, user satisfaction
- Redis metrics: Memory usage, connection counts, operation latencies
- LLM usage tracking: Token consumption, API costs, rate limiting
- Business metrics: Task completion rates, user engagement, conversion

Security and Privacy

- Data encryption: Encrypt sensitive data at rest and in transit
- Access controls: Implement proper authentication and authorization
- Data retention: Automatic cleanup of personal data per regulations
- Audit logging: Track all data access and modifications

Scaling Strategies

- Horizontal scaling: Multiple agent instances with shared Redis state
- Load balancing: Distribute requests across agent instances
- Redis clustering: Scale data storage across multiple nodes
- Caching layers: CDN for static content, Redis for dynamic data
- [Learn about Redis scaling →]()

Cost Optimization

- LLM cost management: Use appropriate models for different tasks
- Redis memory optimization: Efficient data structures and TTL policies
- API rate limiting: Prevent excessive external API calls
- Resource monitoring: Track and optimize compute and storage costs
- [Redis performance optimization →]()

---

Key takeaways

**What makes agents different:**
Agents maintain memory, plan multi-step tasks, and learn from interactions—unlike simple chatbots.

**Why Redis is perfect:**
Sub-millisecond data access, built-in vector search, and flexible data structures designed for agent workflows.

**What you can build:**
Conversational assistants, recommendation engines, and complex multi-agent systems.

Next steps

Ready to build your AI agent with Redis?

**Get started:**
- [Use the agent builder]() to generate your code and get started
- [Redis quick start guide]() for setting up Redis

**Learn more:**
- [Redis Vector Search documentation]()
- [RedisVL Python library]() for vector operations and AI workflows
- [Redis data structures guide](/develop/data-types/)
- [Redis client libraries]() for your programming language

**Deploy and scale:**
- [Redis Cloud]() for managed Redis hosting
- [Redis Software]() for on-premises deployment
- [Performance optimization]() best practices


AI agent builder

Summary: Build custom AI agents powered by Redis with our interactive code generator

How agents work

Overview

Agents use Redis for data storage, vector search, and conversation memory. The interactive builder generates code in your preferred programming language with your choice of model.

Get started

Use the interactive builder below to generate your custom AI agent code:

What are AI agents?

AI agents are intelligent systems that can plan, remember, and take actions to help users accomplish goals. Unlike simple chatbots, agents can remember conversations, plan multi-step tasks, use external tools, and learn from interactions.

Redis powers these capabilities with fast, reliable data storage and retrieval that keeps your agents responsive and intelligent.

**Learn more**: [How agents work](agent-concepts/)

What you can build

Choose from two types of intelligent agents:

- **Recommendation engines**: Personalized product and content recommendations
- **Conversational assistants**: Chatbots with memory and context awareness

The agent builder will generate complete, working code examples for your chosen agent type.

Features

- **Multiple programming languages**: Generate code in Python, with JavaScript (Node.js), Java, and C# coming soon
- **LLM integration**: Support for OpenAI, Anthropic Claude, and Llama 2
- **Redis optimized**: Uses Redis data structures for optimal performance

After you generate your code

Use the **Copy** or **Download** buttons and follow the steps below to test it locally:

1. **Set up your environment**: Install Redis and the required dependencies
2. **Configure your API keys**: Add your LLM provider credentials to environment variables
3. **Test locally**: Start with simple conversations to verify everything works
4. **Deploy and scale**: Use Redis Cloud for production deployments

The generated code includes detailed setup instructions and best practices to get you started quickly. If you want to generate another agent, select the **Start again** button.

Learn more

AI agent resources

- [How agents work](agent-concepts/) - Learn how agents work and why Redis is perfect for them

Redis AI documentation

- [Redis Vector Search]() - Semantic search capabilities
- [Redis Streams](/develop/data-types/streams/) - Real-time data and conversation history
- [AI Notebooks Collection]() - Interactive tutorials and examples
- [Ecosystem Integrations]() - Redis with AI frameworks

Community and support

- Join the [Redis Discord](https://discord.gg/redis) for community support
- Explore [Redis AI Resources on GitHub](https://github.com/redis-developer/redis-ai-resources)
- Watch [AI Video Collection]() for tutorials and demonstrations


Redis video tutorial collection

Summary: Watch video tutorials and demos showcasing Redis in AI applications, from vector search to RAG implementations.

Overview

Explore our collection of video tutorials and demonstrations showcasing how Redis powers AI applications. From vector search fundamentals to advanced RAG implementations, these videos provide practical insights and hands-on examples.

| | | |
|---|---|---|
| [**Long-Term Memory with LangGraph**](https://www.youtube.com/watch?v=fsENEq4F55Q) | [**Short-Term Memory with LangGraph**](https://www.youtube.com/watch?v=k3FUWWEwgfc) | [**What is semantic search?**](https://www.youtube.com/watch?v=o3XN4dImESE) |
| Learn how to implement long-term memory capabilities in AI agents using LangGraph. This video shows you how to build AI systems that can retain and recall information across extended interactions. | Want your AI agents to remember what users tell them? Short-term memory is the key to natural conversations, and in this tutorial, you'll learn how to implement it with LangGraph. | Traditional search matches words — but what if your AI app could match meaning instead? This video explains how semantic search works and why it's essential for modern AI applications. |
| [**What is a semantic cache?**](https://www.youtube.com/watch?v=AtVTT_s8AGc) | [**Building a RAG Pipeline from Scratch with RedisVL**](https://www.youtube.com/watch?v=cCTKmmGO4CY) | [**What is a vector database?**](https://www.youtube.com/watch?v=Yhv19le0sBw) |
| What if you could skip redundant LLM calls and make your AI app faster, cheaper, and smarter? This video breaks down semantic caching and shows how it can transform your AI applications. | Unlock the Power of Retrieval-Augmented Generation (RAG) with RedisVL. This tutorial will show you how to build a complete RAG pipeline from scratch using Redis as your vector database. | Vector databases have been trending recently as they power modern search, recommendations, and AI-driven applications. Learn what vector databases are and how they work. |
| [**Building the future Architecting AI Agents with AWS, LlamaIndex and Redis**](https://www.youtube.com/watch?v=SFWroqAbBM4) | [**Building AI Apps using LangChain**](https://www.youtube.com/watch?v=YhxksXfgsp0) | [**Resources to Learn AI with Redis**](https://www.youtube.com/watch?v=M_WU_fN_lrs) |
| The ins and outs of AI agents: understand their role in breaking down tasks into manageable components for better performance. Learn how to architect AI agents using AWS, LlamaIndex, and Redis. | This series of videos dives into the integration between LangChain and Redis to power AI applications that need runtime speed, scalability, and intelligent data management. | This video shows which resources you can use to learn AI with Redis and build powerful AI applications. |
| [**What Is RAG? Retrieval-Augmented Generation Explained Simply**](https://www.youtube.com/watch?v=xPMQ2cVbUTI) | [**Chunking Strategies Explained**](https://www.youtube.com/watch?v=ZTOtxiWb2bE) | [**What is an embedding model?**](https://www.youtube.com/watch?v=0U1S0WSsPuE) |
| Retrieval-Augmented Generation (RAG) is one of the most powerful architectural patterns in GenAI today—combining the strengths of large language models (LLMs) with real-time, external context from your own data. In this session, learn why it matters and how each component—from query rewriting to dense retrieval to semantic chunking—works behind the scenes to power more accurate, grounded, and up-to-date responses. | Are you interested in building LLM applications that actually work? Your chunking strategy makes all the difference. In this video, get a  break down of the science of text chunking so your embeddings can start answering the right questions to your users. | Everyone’s talking about embedding models lately—but what do they actually do, and why does it matter? This video breaks it down in simple terms and shows how embeddings power search, recommendations, and AI features behind the scenes. |

Additional Resources

| | | |
|---|---|---|
| [**LLM Session Management with Redis**](https://www.youtube.com/watch?v=2jHtSLVUu0w) | [**A Semantic Cache using LangChain**](https://www.youtube.com/watch?v=LRswXEc5chE) | [**Similarity Search using Vector Store**](https://www.youtube.com/watch?v=BtFJdSiFh00) |
| Developers building AI applications require a way to store the conversation history between an LLM and a user. This is important to provide context and maintain coherent conversations across sessions. | One common concern of developers building AI applications is how quickly answers from LLMs will be served to their end users, as well as how much it will cost. Learn how to implement semantic caching using LangChain and Redis. | Similarity search is one of the most popular use cases for developers building AI applications. It allows users to perform searches that can find semantically similar content using vector embeddings. |
| [**Create a New Database on Redis Cloud**](https://www.youtube.com/watch?v=jF89DiC5RqM) | [**Redis Insight: A Developer's Deep Dive**](https://www.youtube.com/watch?v=dINUz_XOZ0M) | [**Redis + Amazon SageMaker for real-time fraud detection demo**](https://www.youtube.com/watch?v=kQKfXi7NfWs) |
| Learn how to create a new database on Redis Cloud in this step-by-step tutorial. Perfect for developers getting started with Redis Cloud for their AI and data applications. | This video breaks down Redis Insight and shows developers how to use this powerful tool for database management and development. | See how Redis integrates with Amazon SageMaker to build real-time fraud detection systems. This demo shows practical applications of Redis in machine learning and AI-powered fraud prevention. |
| [**Redis + Amazon Bedrock in two minutes**](https://www.youtube.com/watch?v=1e2tM5kIJ5Y) | | |
| AWS has announced Redis Cloud as one of the few supported vector databases supported for Amazon Bedrock. Learn how to integrate Redis with Amazon Bedrock for your generative AI applications. | | |

Getting Started

Ready to start building AI applications with Redis? Check out our:

- [Quickstart guides]()
- [Vector search documentation]()
- [AI ecosystem integrations]()
- [Notebook collection]()
- [Vector set data type]()