Using Redis as a Vector Database with Go: Index Creation, Data Insertion, and Vector Search
This article explains how to leverage Redis Stack modules such as RedisJSON, RediSearch, and RedisTimeSeries to store, index, and query high‑dimensional vectors for image‑search services, providing Go code examples for index creation, bulk insertion, memory inspection, and K‑Nearest‑Neighbour vector searches with optional filtering.
Preface
Beyond its well‑known caching capabilities, Redis offers modules like RedisJSON, RediSearch, RedisTimeSeries, and RedisBloom that add JSON handling, full‑text and vector search, time‑series data, and probabilistic structures. All of these can be imported on demand or bundled in Redis Stack for immediate use.
This article briefly describes how Redis can be used as a vector database.
Redis as a Vector Database
Assume we want to build an image‑search service. The core data model includes: photoID: unique identifier for each image userID: identifier of the image owner, usable as a filter vector: the feature vector representing the image
Creating the Index & Inserting Vectors
We store the data in JSON format and use the FT.CREATE command to create an index (required for vector search):
FT.CREATE photos ON JSON
PREFIX 1 photoID: SCORE 1.0
SCHEMA
$.userID as userID NUMERIC
$.vector AS vector VECTOR FLAT 6 TYPE FLOAT32 DIM 512 DISTANCE_METRIC L2The command creates a JSON‑based index named photos that applies to keys prefixed with photoID:. Two fields are indexed: userID (numeric) and vector (a 512‑dimensional FLOAT32 vector using the FLAT similarity algorithm with L2 distance).
Below is a Go implementation that creates the index and inserts 1,000 random 512‑dimensional vectors:
package redis_test
import (
"bytes"
"context"
"encoding/binary"
"encoding/json"
"fmt"
"math/rand"
"strconv"
"github.com/redis/go-redis/v9"
)
func GenVectorArr(dim int) []float32 {
vectors := make([]float32, dim)
for i := 0; i < dim; i++ {
vectors[i] = rand.Float32()
}
return vectors
}
type Photos struct {
ID int `json:"-"`
UserID int `json:"userID"`
Vector []float32 `json:"vector"`
}
var rds *redis.Client
func getRedisClient() *redis.Client {
if rds == nil {
rds = redis.NewClient(&redis.Options{Addr: "your-redis-host", Username: "xxxx", Password: "xxxx"})
}
return rds
}
func CreateVector() {
rdb := getRedisClient()
ctx := context.Background()
rdb.FlushAll(ctx)
// Create index (FT.CREATE ...)
val, err := rdb.Do(ctx, "FT.CREATE", "photos", "ON", "JSON", "PREFIX", "1", "photoID:", "SCORE", "1.0", "SCHEMA", "$.userID", "as", "userID", "NUMERIC", "$.vector", "as", "vector", "VECTOR", "FLAT", "6", "TYPE", "FLOAT32", "DIM", "512", "DISTANCE_METRIC", "L2").Result()
if err != nil { panic(err) }
fmt.Println("FT.CREATE:", val.(string))
// Insert 1000 vectors
for i := 0; i < 1000; i++ {
photo := Photos{ID: 100000 + i, UserID: 200000 + (i / 100), Vector: GenVectorArr(512)}
photobytes, _ := json.Marshal(photo)
if r := rdb.JSONSet(ctx, "photoID:"+strconv.Itoa(photo.ID), "$", photobytes); r.Err() != nil { panic(r.Err()) }
}
}The example uses JSON.SET to store each generated vector.
Memory usage per record can be inspected with JSON.DEBUG MEMORY:
> JSON.DEBUG memory photoID:100000
(integer) 16552Thus a single record occupies roughly 16 KB; 1,000 records need about 16 MB, and one million would require ~16 GB.
Index information can be retrieved with FT.INFO.
Vector Search
Vector search is performed with the FT.SEARCH command.
Example 1 – basic K‑NN search returning the top 10 closest vectors and the associated userID:
FT.SEARCH photos "*=>[KNN 10 @vector $BLOB AS my_scores]"
RETURN 1 $.userID
PARAMS 2
BLOB "query vector"
SORTBY my_scores
DIALECT 2Explanation:
Searches the photos index using K‑NN on the vector field.
Returns only the userID field to avoid transferring large vectors.
Two parameters are passed: the binary blob of the query vector.
Results are sorted by the computed similarity score.
Example 2 – adds a pre‑filter on userID range:
FT.SEARCH photos "(@userID:[200000,200000])=>[KNN $K @vector $BLOB AS my_scores]"
RETURN 1 $.userID
PARAMS 4
BLOB "query vector"
K 3
SORTBY my_scores
DIALECT 2Go code for the filtered search:
func Float32SliceToBytes(data []float32) ([]byte, error) {
buf := new(bytes.Buffer)
if err := binary.Write(buf, binary.LittleEndian, data); err != nil { return nil, err }
return buf.Bytes(), nil
}
func SearchVector() {
rdb := getRedisClient()
ctx := context.Background()
searchVector := GenVectorArr(512)
searchBlob, _ := Float32SliceToBytes(searchVector)
// Basic KNN search
val, err := rdb.Do(ctx, "FT.SEARCH", "photos", "*=>[KNN 10 @vector $BLOB AS my_scores]", "RETURN", "1", "$.userID", "PARAMS", "2", "BLOB", searchBlob, "SORTBY", "my_scores", "DIALECT", "2").Result()
if err != nil { panic(err) }
fmt.Println("FT.SEARCH:", val)
// KNN with userID filter
r2, err := rdb.Do(ctx, "FT.SEARCH", "photos", "(@userID:[200000,200000])=>[KNN $K @vector $BLOB AS my_scores]", "RETURN", "1", "$.userID", "PARAMS", "4", "BLOB", searchBlob, "K", "3", "SORTBY", "my_scores", "DIALECT", "2").Result()
if err != nil { panic(err) }
fmt.Println("FT.SEARCH with filter total results:", r2)
}Performance
Redis published a benchmark article titled “Benchmarking results for vector databases”, concluding that Redis delivers the highest throughput and lowest latency among tested vector stores.
Because vector calculations are CPU‑intensive, Redis employs multi‑threading for search operations to avoid blocking the main event loop.
For modest data volumes, using Redis as a vector database is a practical and high‑performance choice.
References:
https://redis.io/blog/benchmarking-results-for-vector-databases/
https://cookbook.openai.com/examples/vector_databases/redis/getting-started-with-redis-and-openai
https://redis.io/docs/latest/develop/get-started/vector-database/
https://redis.io/docs/latest/develop/interact/search-and-query/advanced-concepts/vectors/
https://redis.io/docs/latest/develop/interact/search-and-query/indexing/
https://redis.io/docs/latest/develop/interact/search-and-query/query/vector-search/
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
System Architect Go
Programming, architecture, application development, message queues, middleware, databases, containerization, big data, image processing, machine learning, AI, personal growth.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
