Skip to main content
Upstash Redis Search can index the entries of a Redis stream. Each stream entry becomes a separate search document, so you can search event fields without scanning the stream or knowing an entry ID.

How stream indexes work

A stream index differs from a JSON, hash, or string index in two ways:
  • It is bound to one exact stream key instead of one or more key prefixes.
  • Each stream entry is a document. The document ID returned by Search is the stream entry ID.
The fields added with XADD provide the document fields. Stream payloads are flat field-value pairs, so schema fields refer to stream fields rather than nested paths.
The stream does not need to exist when you create the index. Entries added later are indexed automatically.

Create a stream index

Use ON STREAM followed by the exact stream key. PREFIX is not supported for stream indexes.
Only one search index can be bound to a stream at a time. To bind the stream to a different index, first drop the existing index with SEARCH.DROP.

Add and search entries

Add entries with regular stream commands. The field names do not need to appear in the schema, but only schema fields are searchable.
The matching result has 1-0 as its document ID. Each result contains the entry ID, relevance score, and field-value pairs. For example, with an illustrative score:
Field values are returned as strings, even when indexed as numeric types. SELECT limits the returned fields; NOCONTENT omits the content entirely. Filtering, highlighting, sorting, pagination, and score functions work with stream indexes as well. Use the returned ID with XRANGE to read the original entry, including fields not selected by the query:
Index updates are asynchronous. Use SEARCH.WAITINDEXING when a query must include preceding writes, especially in tests and setup scripts.
The search document limit also applies to stream entries. When the index reaches its limit, XADD can return an error instead of adding the entry to the stream. Delete or trim entries to reduce the number of indexed documents before adding more.

Schema values

Redis stores stream field values as strings. Search converts each value according to its schema type:
  • U64, I64, and F64 fields require values in the corresponding numeric format.
  • BOOL fields accept true or false.
  • DATE fields require an RFC 3339 timestamp, such as 2026-08-24T09:30:00Z.
  • TEXT, KEYWORD, and FACET fields use string values.
Missing fields, empty values, and values that cannot be converted are omitted from the indexed document. If an entry has no valid schema fields, it is not added to the index. TEXT, KEYWORD, U64, I64, F64, and DATE fields also accept JSON-encoded arrays. Each valid element is indexed as a separate value of the same field. For example, the service field can contain more than one service:
The query matches entry 3-0. Its returned service value is the original JSON-encoded string. BOOL and FACET fields do not support multiple values through JSON arrays. You can use FROM to expose a stream field under a different index field name:
Queries use the schema name (description), while SELECT and returned content use the original stream field name (message).

Existing entries

Creating an index scans entries already present in the stream. Use SKIPINITIALSCAN to index only new entries at first:

Entry deletion and trimming

The index follows the contents of the stream: If a deleted or expired stream is recreated under the same key, new entries are added to the existing index. Consumer-group operations that do not change entry data, such as XACK, do not change the index.
RENAME, RENAMENX, and COPY are not supported for stream keys.

Next steps