{
  "id": "arrays",
  "title": "Redis arrays",
  "url": "https://redis.io/docs/latest/develop/data-types/arrays/",
  "summary": "Introduction to Redis arrays",
  "tags": [
    "docs",
    "develop",
    "stack",
    "oss",
    "rs",
    "rc",
    "kubernetes",
    "clients"
  ],
  "last_updated": "2026-05-26T09:29:27-05:00",
  "page_type": "content",
  "content_hash": "70f92bb8452ea27946a3ad73eaeb2dd470e3f420dca039a24c371b3346164848",
  "sections": [
    {
      "id": "array-command-summary",
      "title": "Array command summary",
      "role": "overview",
      "text": "**18 commands in this group:**\n\n[View all array commands](https://redis.io/commands/?group=array)\n\n| Command | Summary | Complexity | Since |\n|---------|---------|------------|-------|\n| [ARCOUNT](https://redis.io/commands/arcount/) | Returns the number of non-empty elements in an array. | O(1) | 8.8.0 |\n| [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 |\n| [ARDELRANGE](https://redis.io/commands/ardelrange/) | Deletes elements in one or more ranges. | Proportional to the number of existing elements... | 8.8.0 |\n| [ARGET](https://redis.io/commands/arget/) | Gets the value at an index in an array. | O(1) | 8.8.0 |\n| [ARGETRANGE](https://redis.io/commands/argetrange/) | Gets values in a range of indices. | O(N) where N is the range length | 8.8.0 |\n| [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 |\n| [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 |\n| [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 |\n| [ARLASTITEMS](https://redis.io/commands/arlastitems/) | Returns the most recently inserted elements. | O(N) where N is the count | 8.8.0 |\n| [ARLEN](https://redis.io/commands/arlen/) | Returns the length of an array (max index + 1). | O(1) | 8.8.0 |\n\n#### Array command summary (part 2)\n\n| Command | Summary | Complexity | Since |\n|---------|---------|------------|-------|\n| [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 |\n| [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 |\n| [ARNEXT](https://redis.io/commands/arnext/) | Returns the next index ARINSERT would use. | O(1) | 8.8.0 |\n| [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 |\n| [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 |\n| [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 |\n| [ARSEEK](https://redis.io/commands/arseek/) | Sets the ARINSERT / ARRING cursor to a specific index. | O(1) | 8.8.0 |\n| [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 |\n\n\n\nRedis 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."
    },
    {
      "id": "basic-usage",
      "title": "Basic usage",
      "role": "content",
      "text": "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.\n\n[code example]\n\nTo 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):\n\n[code example]"
    },
    {
      "id": "array-length-vs-element-count",
      "title": "Array length vs. element count",
      "role": "content",
      "text": "Redis arrays expose two distinct size measurements:\n\n- [`ARLEN`](https://redis.io/docs/latest/commands/arlen) returns the *logical length*: the highest set index plus one.\n- [`ARCOUNT`](https://redis.io/docs/latest/commands/arcount) returns the number of *non-empty* elements.\n\nFor a sparse array, these values can differ substantially:\n\n[code example]"
    },
    {
      "id": "reading-ranges",
      "title": "Reading ranges",
      "role": "content",
      "text": "[`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:\n\n[code example]\n\nTo 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:\n\n[code example]"
    },
    {
      "id": "sequential-insertion",
      "title": "Sequential insertion",
      "role": "content",
      "text": "[`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:\n\n[code example]"
    },
    {
      "id": "ring-buffer-mode",
      "title": "Ring buffer mode",
      "role": "content",
      "text": "[`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:\n\n[code example]\n\n[`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:\n\n[code example]"
    },
    {
      "id": "aggregate-operations",
      "title": "Aggregate operations",
      "role": "content",
      "text": "[`AROP`](https://redis.io/docs/latest/commands/arop) performs a single-pass aggregate over a contiguous range of elements:\n\n| Operation | Description |\n|-----------|-------------|\n| `SUM` | Sum of numeric values |\n| `MIN` | Minimum numeric value |\n| `MAX` | Maximum numeric value |\n| `AND` / `OR` / `XOR` | Bitwise operation on integer values |\n| `MATCH value` | Count of elements equal to `value` |\n| `USED` | Count of non-empty elements in the range |\n\n[code example]"
    },
    {
      "id": "searching-elements",
      "title": "Searching elements",
      "role": "content",
      "text": "[`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.\n\nThis is particularly useful when an array stores line-indexed text such as a log file, where each element holds one line:\n\n[code example]\n\nThe 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."
    },
    {
      "id": "deleting-elements",
      "title": "Deleting elements",
      "role": "content",
      "text": "[`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:\n\n[code example]\n\nDeleting the last remaining element removes the key entirely."
    },
    {
      "id": "introspection",
      "title": "Introspection",
      "role": "content",
      "text": "[`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:\n\n[code example]"
    },
    {
      "id": "configuration",
      "title": "Configuration",
      "role": "configuration",
      "text": "The following configuration parameters affect array behavior:\n- `array-slice-size`\n- `array-sparse-kmax`\n- `array-sparse-kmin`\n\nSee the [Redis configuration page](https://redis.io/docs/latest/operate/oss_and_stack/management/config) for details."
    },
    {
      "id": "performance",
      "title": "Performance",
      "role": "performance",
      "text": "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."
    },
    {
      "id": "alternatives",
      "title": "Alternatives",
      "role": "content",
      "text": "Arrays complement rather than replace the other Redis collection types:\n\n- 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.\n- Use [Redis hashes](https://redis.io/docs/latest/develop/data-types/hashes) when values are addressed by field name rather than by numeric index.\n- 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."
    },
    {
      "id": "limits",
      "title": "Limits",
      "role": "limits",
      "text": "[`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."
    }
  ],
  "examples": [
    {
      "id": "basic-usage-ex0",
      "language": "plaintext",
      "code": "> ARSET events:1 0 \"login\" \"click\" \"purchase\"\n(integer) 3\n> ARGET events:1 0\n\"login\"\n> ARGET events:1 999\n(nil)",
      "section_id": "basic-usage"
    },
    {
      "id": "basic-usage-ex1",
      "language": "plaintext",
      "code": "> ARMSET metrics 0 \"10\" 5 \"20\" 100 \"30\"\n(integer) 3\n> ARMGET metrics 0 5 100 999\n1) \"10\"\n2) \"20\"\n3) \"30\"\n4) (nil)",
      "section_id": "basic-usage"
    },
    {
      "id": "array-length-vs-element-count-ex0",
      "language": "plaintext",
      "code": "> ARSET sparse 0 \"a\"\n(integer) 1\n> ARSET sparse 1000000 \"b\"\n(integer) 1\n> ARLEN sparse\n(integer) 1000001\n> ARCOUNT sparse\n(integer) 2",
      "section_id": "array-length-vs-element-count"
    },
    {
      "id": "reading-ranges-ex0",
      "language": "plaintext",
      "code": "> ARMSET seq 0 \"a\" 1 \"b\" 3 \"d\"\n(integer) 3\n> ARGETRANGE seq 0 3\n1) \"a\"\n2) \"b\"\n3) (nil)\n4) \"d\"",
      "section_id": "reading-ranges"
    },
    {
      "id": "reading-ranges-ex1",
      "language": "plaintext",
      "code": "> ARSCAN seq 0 3\n1) (integer) 0\n2) \"a\"\n3) (integer) 1\n4) \"b\"\n5) (integer) 3\n6) \"d\"",
      "section_id": "reading-ranges"
    },
    {
      "id": "sequential-insertion-ex0",
      "language": "plaintext",
      "code": "> ARINSERT log \"event1\"\n(integer) 0\n> ARINSERT log \"event2\"\n(integer) 1\n> ARNEXT log\n(integer) 2\n> ARSEEK log 10\n(integer) 1\n> ARINSERT log \"event3\"\n(integer) 10",
      "section_id": "sequential-insertion"
    },
    {
      "id": "ring-buffer-mode-ex0",
      "language": "plaintext",
      "code": "> ARRING readings 3 \"v0\"\n(integer) 0\n> ARRING readings 3 \"v1\"\n(integer) 1\n> ARRING readings 3 \"v2\"\n(integer) 2\n> ARRING readings 3 \"v3\"\n(integer) 0\n> ARGET readings 0\n\"v3\"",
      "section_id": "ring-buffer-mode"
    },
    {
      "id": "ring-buffer-mode-ex1",
      "language": "plaintext",
      "code": "> ARLASTITEMS readings 3\n1) \"v1\"\n2) \"v2\"\n3) \"v3\"\n> ARLASTITEMS readings 3 REV\n1) \"v3\"\n2) \"v2\"\n3) \"v1\"",
      "section_id": "ring-buffer-mode"
    },
    {
      "id": "aggregate-operations-ex0",
      "language": "plaintext",
      "code": "> ARMSET scores 0 \"10\" 1 \"20\" 2 \"30\"\n(integer) 3\n> AROP scores 0 2 SUM\n\"60\"\n> AROP scores 0 2 MAX\n\"30\"\n> AROP scores 0 2 MATCH \"10\"\n(integer) 1",
      "section_id": "aggregate-operations"
    },
    {
      "id": "searching-elements-ex0",
      "language": "plaintext",
      "code": "> ARMSET log 0 \"boot: ok\" 1 \"warn: disk\" 2 \"ERROR: cpu\" 3 \"info: ready\" 4 \"error: net\"\n(integer) 5\n> ARGREP log - + MATCH \"error\" NOCASE\n1) (integer) 2\n2) (integer) 4\n> ARGREP log 0 4 GLOB \"warn:*\" OR GLOB \"error:*\" WITHVALUES\n1) (integer) 1\n2) \"warn: disk\"\n3) (integer) 4\n4) \"error: net\"",
      "section_id": "searching-elements"
    },
    {
      "id": "deleting-elements-ex0",
      "language": "plaintext",
      "code": "> ARDEL scores 1\n(integer) 1\n> ARDELRANGE scores 0 2\n(integer) 2",
      "section_id": "deleting-elements"
    },
    {
      "id": "introspection-ex0",
      "language": "plaintext",
      "code": "> ARINFO readings\n 1) \"len\"\n 2) (integer) 3\n 3) \"count\"\n 4) (integer) 3\n 5) \"next-insert-index\"\n 6) (integer) 0\n...",
      "section_id": "introspection"
    }
  ]
}
