Redis Stack (modules in Redis 8+).

Install

docker run -d -p 6379:6379 redis/redis-stack-server:latest

Or use redis-stack package (includes RedisInsight UI).

RedisJSON

JSON.SET user:1 $ '{"name":"Alice","age":30,"tags":["admin","beta"]}'
JSON.GET user:1
JSON.GET user:1 $.name
JSON.GET user:1 $..tags
JSON.SET user:1 $.age 31
JSON.ARRAPPEND user:1 $.tags '"new"'
JSON.NUMINCRBY user:1 $.age 1
JSON.DEL user:1 $.tags
JSON.OBJKEYS user:1
JSON.TYPE user:1 $.tags

RediSearch (full-text + secondary indexing)

FT.CREATE idx ON JSON PREFIX 1 user: SCHEMA $.name AS name TEXT $.age AS age NUMERIC SORTABLE $.tags[*] AS tags TAG

FT.SEARCH idx "alice"
FT.SEARCH idx "@age:[20 40]"
FT.SEARCH idx "@tags:{admin}"
FT.SEARCH idx "@name:alice @age:[25 35]"
FT.SEARCH idx "*" LIMIT 0 10 SORTBY age DESC

FT.AGGREGATE idx "*" GROUPBY 1 @tags REDUCE COUNT 0 AS c

Used by Redis OM clients (Python/Node).

FT.CREATE idx ON HASH SCHEMA embedding VECTOR HNSW 6 TYPE FLOAT32 DIM 1536 DISTANCE_METRIC COSINE
r.hset(f"doc:{i}", mapping={
    "text": text,
    "embedding": np.array(embed(text), dtype=np.float32).tobytes(),
})

# Query
q_vec = np.array(embed(query), dtype=np.float32).tobytes()
res = r.execute_command(
    "FT.SEARCH", "idx",
    "*=>[KNN 5 @embedding $vec AS score]",
    "PARAMS", "2", "vec", q_vec,
    "RETURN", "2", "text", "score",
    "DIALECT", "2",
)

Hybrid (text + vector)

FT.SEARCH idx "@category:{news}=>[KNN 5 @embedding $vec]"

TimeSeries

TS.CREATE temp:nyc RETENTION 86400000 LABELS city ny
TS.ADD temp:nyc * 23.5
TS.MADD temp:nyc 1700000000 22 temp:la 1700000000 28
TS.RANGE temp:nyc - + AGGREGATION avg 60000
TS.MRANGE - + AGGREGATION avg 60000 FILTER city=ny
TS.CREATERULE temp:nyc temp:nyc:hourly AGGREGATION avg 3600000

Time-series storage in Redis.

Bloom filters

BF.RESERVE filter 0.01 1000
BF.ADD filter "item"
BF.EXISTS filter "item"
BF.MEXISTS filter "a" "b" "c"
BF.SCANDUMP / BF.LOADCHUNK

For “have I seen this?” with bounded memory.

Cuckoo filters

Like Bloom but supports delete:

CF.RESERVE filter 1000
CF.ADD filter "a"
CF.DEL filter "a"
CF.EXISTS filter "a"

Count-min sketch

CMS.INITBYDIM cms 1000 5
CMS.INCRBY cms "a" 1 "b" 5
CMS.QUERY cms "a" "b"

Approximate frequency counter.

Top-K

TOPK.RESERVE topk 10 1000 5 0.9
TOPK.ADD topk "a" "b" "a" "c"
TOPK.LIST topk
TOPK.COUNT topk "a"

Graphs (RedisGraph)

GRAPH.QUERY social "CREATE (:Person {name:'Alice'})-[:KNOWS]->(:Person {name:'Bob'})"
GRAPH.QUERY social "MATCH (p:Person)-[:KNOWS]->(f) RETURN p.name, f.name"

(Note: RedisGraph deprecated; consider FalkorDB / Neo4j.)

Common uses

  • JSON-doc store with search → mini Mongo.
  • Vector for embeddings.
  • Bloom for dedup / quick membership.
  • TimeSeries for metrics.

Common mistakes

  • Using OSS Redis with Stack commands → unknown command.
  • Index per query (create once).
  • Forgetting to update index on schema change.
  • Vector field binary encoding wrong dim/dtype.

Read this next

If you want my Stack-based search setup, it’s at rajpoot.dev .


Building something AI-, backend-, or data-heavy and want a second pair of eyes? I do consulting and freelance work — see my projects and ways to reach me at rajpoot.dev .