# Redis arrays

```json metadata
{
  "title": "Redis arrays",
  "description": "Introduction to Redis arrays",
  "categories": ["docs","develop","stack","oss","rs","rc","kubernetes","clients"],
  "tableOfContents": {"sections":[{"id":"basic-usage","title":"Basic usage"},{"id":"array-length-vs-element-count","title":"Array length vs. element count"},{"id":"reading-ranges","title":"Reading ranges"},{"id":"sequential-insertion","title":"Sequential insertion"},{"id":"ring-buffer-mode","title":"Ring buffer mode"},{"id":"aggregate-operations","title":"Aggregate operations"},{"id":"searching-elements","title":"Searching elements"},{"id":"deleting-elements","title":"Deleting elements"},{"id":"introspection","title":"Introspection"},{"id":"configuration","title":"Configuration"},{"id":"performance","title":"Performance"},{"id":"alternatives","title":"Alternatives"},{"id":"limits","title":"Limits"}]}

,
  "codeExamples": []
}
```
### Array command summary

**18 commands in this group:**

[View all array commands](https://redis.io/commands/?group=array)

| Command | Summary | Complexity | Since |
|---------|---------|------------|-------|
| [ARCOUNT](https://redis.io/commands/arcount/) | Returns the number of non-empty elements in an array. | O(1) | 8.8.0 |
| [ARDEL](https://redis.io/commands/ardel/) | Deletes elements at the specified indices in an array. | O(N) where N is the number of indices to delete | 8.8.0 |
| [ARDELRANGE](https://redis.io/commands/ardelrange/) | Deletes elements in one or more ranges. | Proportional to the number of existing elements... | 8.8.0 |
| [ARGET](https://redis.io/commands/arget/) | Gets the value at an index in an array. | O(1) | 8.8.0 |
| [ARGETRANGE](https://redis.io/commands/argetrange/) | Gets values in a range of indices. | O(N) where N is the range length | 8.8.0 |
| [ARGREP](https://redis.io/commands/argrep/) | Searches array elements in a range using textual predicates. | O(P * C) where P is the number of visited posit... | 8.8.0 |
| [ARINFO](https://redis.io/commands/arinfo/) | Returns metadata about an array. | O(1), or O(N) with FULL option where N is the n... | 8.8.0 |
| [ARINSERT](https://redis.io/commands/arinsert/) | Inserts one or more values at consecutive indices. | O(N) where N is the number of values | 8.8.0 |
| [ARLASTITEMS](https://redis.io/commands/arlastitems/) | Returns the most recently inserted elements. | O(N) where N is the count | 8.8.0 |
| [ARLEN](https://redis.io/commands/arlen/) | Returns the length of an array (max index + 1). | O(1) | 8.8.0 |

#### Array command summary (part 2)

| Command | Summary | Complexity | Since |
|---------|---------|------------|-------|
| [ARMGET](https://redis.io/commands/armget/) | Gets values at multiple indices in an array. | O(N) where N is the number of indices | 8.8.0 |
| [ARMSET](https://redis.io/commands/armset/) | Sets multiple index-value pairs in an array. | O(N) where N is the number of pairs | 8.8.0 |
| [ARNEXT](https://redis.io/commands/arnext/) | Returns the next index ARINSERT would use. | O(1) | 8.8.0 |
| [AROP](https://redis.io/commands/arop/) | Performs aggregate operations on array elements in a range. | O(P) where P is visited positions in touched sl... | 8.8.0 |
| [ARRING](https://redis.io/commands/arring/) | Inserts values into a ring buffer of specified size, wrapping and truncating as needed. | O(M) normally, O(N+M) on ring resize, where N i... | 8.8.0 |
| [ARSCAN](https://redis.io/commands/arscan/) | Iterates existing elements in a range, returning index-value pairs. | O(P) where P is visited positions in touched sl... | 8.8.0 |
| [ARSEEK](https://redis.io/commands/arseek/) | Sets the ARINSERT / ARRING cursor to a specific index. | O(1) | 8.8.0 |
| [ARSET](https://redis.io/commands/arset/) | Sets one or more contiguous values starting at an index in an array. | O(N) where N is the number of values | 8.8.0 |



Redis arrays are sparse, index-addressable data structures that map integer indexes (in the range 0 to 2⁶⁴−1) to string values. Unlike lists, elements are accessed directly by index rather than by position in a sequence, and you can set any index without allocating the gaps between occupied slots. This makes arrays well-suited for timestamped event logs, ring buffers over streaming measurements, sliding-window analytics, and other workloads that involve sparse or high-index access patterns.

## Basic usage

Use [`ARSET`](https://redis.io/docs/latest/commands/arset) to write one or more contiguous values starting at a given index, and [`ARGET`](https://redis.io/docs/latest/commands/arget) to read the value at an index. Accessing an unset index returns a nil reply.

```
> ARSET events:1 0 "login" "click" "purchase"
(integer) 3
> ARGET events:1 0
"login"
> ARGET events:1 999
(nil)
```

To write values at arbitrary, non-contiguous indexes, use [`ARMSET`](https://redis.io/docs/latest/commands/armset). To read several indexes in one round trip, use [`ARMGET`](https://redis.io/docs/latest/commands/armget):

```
> ARMSET metrics 0 "10" 5 "20" 100 "30"
(integer) 3
> ARMGET metrics 0 5 100 999
1) "10"
2) "20"
3) "30"
4) (nil)
```

## Array length vs. element count

Redis arrays expose two distinct size measurements:

- [`ARLEN`](https://redis.io/docs/latest/commands/arlen) returns the *logical length*: the highest set index plus one.
- [`ARCOUNT`](https://redis.io/docs/latest/commands/arcount) returns the number of *non-empty* elements.

For a sparse array, these values can differ substantially:

```
> ARSET sparse 0 "a"
(integer) 1
> ARSET sparse 1000000 "b"
(integer) 1
> ARLEN sparse
(integer) 1000001
> ARCOUNT sparse
(integer) 2
```

## Reading ranges

[`ARGETRANGE`](https://redis.io/docs/latest/commands/argetrange) returns every position in a range—including empty slots as nil—in index order. Reversing `start` and `end` reverses the direction:

```
> ARMSET seq 0 "a" 1 "b" 3 "d"
(integer) 3
> ARGETRANGE seq 0 3
1) "a"
2) "b"
3) (nil)
4) "d"
```

To iterate only the elements that exist and retrieve their indexes alongside their values, use [`ARSCAN`](https://redis.io/docs/latest/commands/arscan). It skips empty slots and returns a flat list of alternating index-value pairs, with an optional `LIMIT` to cap the result size:

```
> ARSCAN seq 0 3
1) (integer) 0
2) "a"
3) (integer) 1
4) "b"
5) (integer) 3
6) "d"
```

## Sequential insertion

[`ARINSERT`](https://redis.io/docs/latest/commands/arinsert) appends values using an internal cursor that advances automatically after each call. Use [`ARNEXT`](https://redis.io/docs/latest/commands/arnext) to inspect where the next insert would land, and [`ARSEEK`](https://redis.io/docs/latest/commands/arseek) to reposition the cursor:

```
> ARINSERT log "event1"
(integer) 0
> ARINSERT log "event2"
(integer) 1
> ARNEXT log
(integer) 2
> ARSEEK log 10
(integer) 1
> ARINSERT log "event3"
(integer) 10
```

## Ring buffer mode

[`ARRING`](https://redis.io/docs/latest/commands/arring) turns an array into a fixed-size circular buffer. Each call inserts a value at `insert_idx % size`, wrapping back to index `0` once the window is full and overwriting the oldest entry:

```
> ARRING readings 3 "v0"
(integer) 0
> ARRING readings 3 "v1"
(integer) 1
> ARRING readings 3 "v2"
(integer) 2
> ARRING readings 3 "v3"
(integer) 0
> ARGET readings 0
"v3"
```

[`ARLASTITEMS`](https://redis.io/docs/latest/commands/arlastitems) retrieves the *N* most recently inserted elements in chronological order. Pass the `REV` flag to reverse the order:

```
> ARLASTITEMS readings 3
1) "v1"
2) "v2"
3) "v3"
> ARLASTITEMS readings 3 REV
1) "v3"
2) "v2"
3) "v1"
```

## Aggregate operations

[`AROP`](https://redis.io/docs/latest/commands/arop) performs a single-pass aggregate over a contiguous range of elements:

| Operation | Description |
|-----------|-------------|
| `SUM` | Sum of numeric values |
| `MIN` | Minimum numeric value |
| `MAX` | Maximum numeric value |
| `AND` / `OR` / `XOR` | Bitwise operation on integer values |
| `MATCH value` | Count of elements equal to `value` |
| `USED` | Count of non-empty elements in the range |

```
> ARMSET scores 0 "10" 1 "20" 2 "30"
(integer) 3
> AROP scores 0 2 SUM
"60"
> AROP scores 0 2 MAX
"30"
> AROP scores 0 2 MATCH "10"
(integer) 1
```

## Searching elements

[`ARGREP`](https://redis.io/docs/latest/commands/argrep) finds elements in a range whose values match one or more textual predicates and returns their indexes. Empty slots are skipped. Four predicate forms are supported: `EXACT` (full equality), `MATCH` (substring), `GLOB` (the same wildcard syntax as [`SCAN`](https://redis.io/docs/latest/commands/scan) `MATCH`), and `RE` (regular expression). Multiple predicates are combined with `OR` by default, or with `AND` when the option is given. Pass `NOCASE` for case-insensitive comparisons, `WITHVALUES` to return matching values alongside their indexes, and `LIMIT` to cap the number of matches.

This is particularly useful when an array stores line-indexed text such as a log file, where each element holds one line:

```
> ARMSET log 0 "boot: ok" 1 "warn: disk" 2 "ERROR: cpu" 3 "info: ready" 4 "error: net"
(integer) 5
> ARGREP log - + MATCH "error" NOCASE
1) (integer) 2
2) (integer) 4
> ARGREP log 0 4 GLOB "warn:*" OR GLOB "error:*" WITHVALUES
1) (integer) 1
2) "warn: disk"
3) (integer) 4
4) "error: net"
```

The special values `-` and `+` denote the first and last index of the array. Combined with [ring buffer mode](#ring-buffer-mode), this lets a fixed-size array hold the most recent *N* log lines and be searched in place.

## Deleting elements

[`ARDEL`](https://redis.io/docs/latest/commands/ardel) deletes one or more elements by index and returns the count of elements actually removed. [`ARDELRANGE`](https://redis.io/docs/latest/commands/ardelrange) removes all elements within an index range; reversing `start` and `end` is supported:

```
> ARDEL scores 1
(integer) 1
> ARDELRANGE scores 0 2
(integer) 2
```

Deleting the last remaining element removes the key entirely.

## Introspection

[`ARINFO`](https://redis.io/docs/latest/commands/arinfo) returns metadata about an array's internal structure, including its logical length, element count, and next insert index. Pass the `FULL` option to include per-slice statistics such as fill rates and counts of dense versus sparse slices:

```
> ARINFO readings
 1) "len"
 2) (integer) 3
 3) "count"
 4) (integer) 3
 5) "next-insert-index"
 6) (integer) 0
...
```

## Configuration

The following configuration parameters affect array behavior:
- `array-slice-size`
- `array-sparse-kmax`
- `array-sparse-kmin`

See the [Redis configuration page](https://redis.io/docs/latest/operate/oss_and_stack/management/config) for details.

## Performance

Most array commands are O(1), including [`ARSET`](https://redis.io/docs/latest/commands/arset), [`ARGET`](https://redis.io/docs/latest/commands/arget), [`ARDEL`](https://redis.io/docs/latest/commands/ardel), [`ARINSERT`](https://redis.io/docs/latest/commands/arinsert), [`ARNEXT`](https://redis.io/docs/latest/commands/arnext), [`ARSEEK`](https://redis.io/docs/latest/commands/arseek), [`ARCOUNT`](https://redis.io/docs/latest/commands/arcount), and [`ARLEN`](https://redis.io/docs/latest/commands/arlen). Operations that touch N elements—such as [`ARGETRANGE`](https://redis.io/docs/latest/commands/argetrange), [`ARSCAN`](https://redis.io/docs/latest/commands/arscan), [`ARDELRANGE`](https://redis.io/docs/latest/commands/ardelrange), [`AROP`](https://redis.io/docs/latest/commands/arop), and [`ARLASTITEMS`](https://redis.io/docs/latest/commands/arlastitems)—are O(N). The underlying sliced-array encoding handles both dense and sparse access patterns efficiently, so large index gaps consume very little memory.

## Alternatives

Arrays complement rather than replace the other Redis collection types:

- Use [Redis lists](https://redis.io/docs/latest/develop/data-types/lists) when you need push/pop operations at either end, or when you need to insert elements between existing ones.
- Use [Redis hashes](https://redis.io/docs/latest/develop/data-types/hashes) when values are addressed by field name rather than by numeric index.
- Use [Redis streams](https://redis.io/docs/latest/develop/data-types/streams) when you need an append-only event log with consumer groups and acknowledgements.

## Limits

[`ARGETRANGE`](https://redis.io/docs/latest/commands/argetrange) enforces a hard limit of 1,000,000 elements per call to guard against accidentally large range reads.

