Migrating production infrastructure? Get up to ₹10,000 in migration credits. Apply now
voroaBlog
Key Value

Redis Vector Database: Vector Sets Tested on Memory and Recall

· · 8 min read

Redis as a vector database, vector sets tested on memory per vector, query time and recall

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

Advertisement

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

text
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:

js
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%

Bar chart: memory per 384-dimension vector and recall at 10 for three formats - full precision 2,295 bytes and 100 percent, 8-bit 1,142 bytes and 98.7 percent, binary 805 bytes and 36.4 percent

What we found.

  1. 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.
  2. 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.
  3. 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.
  4. 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:

text
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 support@getvoroa.com.

Advertisement