Redis Vector Database: Vector Sets Tested on Memory and Recall
Sagar Tayde · · 8 min read
Running a Redis vector database means storing embeddings in Redis, the lists of numbers an AI model produces for a piece of text or an image, and asking Redis for the ones most similar to a query. Redis 8 added a data type for exactly this, vector sets, alongside the older search engine. This guide is for developers adding semantic search, recommendations or retrieval for an AI feature. It explains the options, then reports what we measured when we loaded 20,000 embeddings into Redis 8.10.3 in three storage formats: memory per vector, insert speed, query time and how often the results matched an exact search.
On this page
- Two ways to store vectors in Redis
- Vector sets in five commands
- What we measured
- Quantization: the setting that decides memory
- How many vectors fit in your store
- Filtering results by attributes
- Redis or pgvector?
- Before you go to production
- FAQ
Two ways to store vectors in Redis
| Vector sets | Query engine (search) | |
|---|---|---|
| Added in | Redis 8 (introduced as beta) | Earlier, as a module; part of Redis 8’s core distribution |
| Model | One key holds a set of named vectors | Vectors as fields inside hashes or JSON documents, with an index |
| Commands | VADD, VSIM, VREM, VSETATTR |
FT.CREATE, FT.SEARCH |
| Index | HNSW, built automatically | HNSW or flat, defined in the index |
| Best for | Simple similarity search with light filtering | Combining vector search with full-text and numeric queries |
| Valkey | Not available | The separate valkey-search module |
Vector sets are the simplest way in, and they are what we tested. The rest of this guide uses them.
Vector sets in five commands
VADD docs VALUES 3 0.12 0.48 0.31 doc:1 add a vector named doc:1
VSIM docs VALUES 3 0.10 0.50 0.30 COUNT 5 the 5 most similar
VSIM docs ELE doc:1 COUNT 5 neighbours of an existing item
VREM docs doc:1 remove one
VINFO docs dimensions, size, quantization
From Node.js with ioredis, sending vectors as binary float32 is faster than text:
import Redis from 'ioredis';
const redis = new Redis(process.env.REDIS_URL);
const f32 = (arr) => Buffer.from(new Float32Array(arr).buffer);
// store: embedding is an array of numbers from your model, e.g. 384 or 1536 long
await redis.call('VADD', 'docs', 'FP32', f32(embedding), `doc:${id}`);
// search: the 10 closest items to a query embedding
const ids = await redis.call('VSIM', 'docs', 'FP32', f32(queryEmbedding), 'COUNT', 10);
Vector sets compare by cosine similarity, so normalised embeddings from common text models work as they come.
What we measured
Setup. Redis 8.10.3 built from source, in a Linux virtual machine (WSL2) on a laptop, with a Node.js 24 client on the same laptop. We generated 20,000 synthetic 384-dimension vectors, a common size for small sentence-embedding models, grouped around 200 centres so that they behave more like real topics than pure noise, plus 200 query vectors from the same distribution. For each storage format we inserted all 20,000 in pipelined batches, ran the 200 queries one at a time asking for the 10 nearest, and compared each answer with an exact brute-force search. Measured 7 November 2026.
Format (VADD option) |
Memory per vector | Insert rate | Query time, median (p99) | Recall@10 |
|---|---|---|---|---|
Full precision (NOQUANT) |
2,295 bytes | 800 per second | 1.73 ms (10.42 ms) | 100.0% |
8-bit, the default (Q8) |
1,142 bytes | 1,921 per second | 1.25 ms (3.74 ms) | 98.7% |
Binary (BIN) |
805 bytes | 3,695 per second | 1.02 ms (4.25 ms) | 36.4% |

What we found.
- The default is the right default. 8-bit storage halved memory against full precision and still returned 98.7% of the exact top-10 results, while inserting more than twice as fast.
- Binary is a trap for this kind of data. It saved almost another third of the memory but found only 36% of the true neighbours. It can suit models designed for binary embeddings; test before you use it.
- Queries were about a millisecond. All three formats answered in 1 to 2 ms at the median on 20,000 vectors. Most of a real request’s time will be spent creating the query embedding, not searching.
- The index costs extra. A raw 384-dimension float32 vector is 1,536 bytes; full precision used 2,295 bytes per vector, the difference being the graph that makes search fast.
Synthetic data is kinder or harsher than your own depending on the model, so treat the recall figures as a guide and check recall on a sample of your real queries.
Quantization: the setting that decides memory
Quantization stores each number with fewer bits. VADD uses 8-bit by default, which you can confirm
with VINFO (it reports quant-type int8). Use NOQUANT only if your results must match an exact search
as closely as possible, and BIN only if your embedding model is designed for it. The choice is made
when the first vector is added to a key, so decide before you load data. The full option list is in the
vector sets documentation.
How many vectors fit in your store
Plain division of the space by the measured size per vector, before attributes and headroom (1 MB = 1,048,576 bytes):
| Store memory available for data | 384-dimension vectors, 8-bit | 1,536-dimension vectors, 8-bit (estimate) |
|---|---|---|
| 75 MB | about 69,000 | about 34,000 |
| 600 MB | about 550,000 | about 270,000 |
| 6 GB | about 5.6 million | about 2.8 million |
The 1,536-dimension column is our estimate: in our test about 384 bytes of each 8-bit vector was the vector itself and about 760 bytes the index, so we scaled only the vector part by four, to about 2.3 KB. Measure your own. Remember that a managed store’s advertised size is not all available for data. On Voroa, for example, up to 40% of each instance can be held back for the nightly save, so a 1 GB store has about 600 MB for data.
Filtering results by attributes
Real searches usually need a filter: only this user’s documents, only products in stock. Vector sets let you attach a small JSON object to each item and filter on it during the search:
VSETATTR docs doc:1 '{"lang":"hi","year":2026}'
VSIM docs VALUES 3 0.10 0.50 0.30 COUNT 5 FILTER '.lang == "hi" and .year >= 2025'
Filtering works best when many items match. If a filter keeps only a tiny fraction of the set, results can come back slower or fewer than you asked for, because the search walks past many non-matching items. For heavily filtered search, the query engine or a database with proper indexes is a better fit.
Redis or pgvector?
Both are reasonable. The question is where the rest of your data lives.
| Redis vector sets | Postgres with pgvector | |
|---|---|---|
| Speed | About 1 ms per query in our test | Fast with an HNSW index; depends on the query plan |
| Memory | All vectors held in RAM | Index can live on disk, data on disk |
| Filtering | Simple attribute filters | Full SQL: joins, permissions, any condition |
| Durability | As good as your Redis persistence | A real database, with backups and transactions |
| Best when | A fast similarity layer over data kept elsewhere | Vectors belong next to the rows they describe |
Choose Redis when you need very low latency and the vector set is a cache or a derived index you can rebuild. Choose pgvector when vectors sit beside your business data and you want SQL filters, transactions and backups in one place. We covered that route in Postgres as a vector database.
Before you go to production
- Check your engine version. Vector sets need Redis 8 or later. Valkey does not have them; it offers vector search through its separate search module. See Valkey vs Redis.
- Plan for rebuilds. Keep the source text and model version in your database, so you can re-embed and reload when you change models. Vectors from different models cannot be mixed in one set.
- Persistence. Vectors held only in memory are lost on a restart without persistence; re-embedding everything is slow and costs API money. Use a store that writes to disk.
- Do not evict. A vector set is one key. An eviction policy that removes keys under memory pressure can delete your entire index at once. Use a no-eviction setting, and watch memory.
- Keep it close. Each search is a round trip; keep the store in the same region as the app that creates the query embedding.
Vector search on Voroa
Voroa’s key value store runs Redis 7.4 today, which does not have vector sets, so it is not the place for this. For vector search on Voroa, use managed PostgreSQL with the pgvector extension, which you can turn on from the database’s settings on a paid plan; the steps are in enabling PostgreSQL extensions. Your web services reach it over the private network in Mumbai. The key value store remains a good fit for caching the results of those searches; see the managed Redis page.
FAQ
Can Redis be used as a vector database? Yes. Redis 8 has vector sets for similarity search, and its query engine supports vector indexes inside hashes and JSON documents.
How much memory does a vector take in Redis? In our test, a 384-dimension vector took about 1,142 bytes with the default 8-bit format and 2,295 bytes at full precision, including the search index.
How accurate is Redis vector search? With the default format, 98.7% of the exact top-10 results in our test, and 100% at full precision. Binary storage dropped to 36% on our data.
Is Redis faster than pgvector? Redis answered our queries in about a millisecond from memory. pgvector can also be fast with an HNSW index, and it offers SQL filters and durability. Pick by where your data lives.
Does Valkey support vector sets? No. Valkey provides vector search through the valkey-search module, which uses a different set of commands.
What embedding size should I use? That is set by your model, for example 384 for small sentence models and 1,536 or more for larger ones. Memory grows roughly in proportion to the size.
Tested 7 November 2026 with Redis 8.10.3 in WSL2 on a laptop, using synthetic embeddings. Found something out of date? Write to [email protected].