DEV Community

Cover image for I added pgvector support to my .NET AI memory library
Aftab Bashir
Aftab Bashir

Posted on

I added pgvector support to my .NET AI memory library

BlazorMemory has had EF Core storage from the start. It works. But there is a problem with how it handles search.

The current EfCoreMemoryStore loads every memory for a user into C#, then runs cosine similarity in a loop. For a user with 50 memories that is fine. For a user with 5,000 it is a full table scan on every query.

v0.6.0 ships a new package that fixes this properly.

BlazorMemory.Storage.Pgvector

The pgvector adapter moves vector search into PostgreSQL. Instead of loading everything and computing in C#, it runs a single SQL query using the <=> cosine distance operator.

SELECT * FROM "Memories"
WHERE "UserId" = @userId
ORDER BY "Embedding" <=> @queryVector
LIMIT 5;
Enter fullscreen mode Exit fullscreen mode

PostgreSQL handles the math. The .NET code just maps the results.

Setup

dotnet add package BlazorMemory.Storage.Pgvector
Enter fullscreen mode Exit fullscreen mode

You need PostgreSQL with the pgvector extension. If you are on a fresh database:

CREATE EXTENSION IF NOT EXISTS vector;
Enter fullscreen mode Exit fullscreen mode

Then wire it up:

builder.Services
    .AddBlazorMemory()
    .UsePgvectorStorage<AppDbContext>()
    .UseOpenAiEmbeddings(apiKey)
    .UseOpenAiExtractor(apiKey);
Enter fullscreen mode Exit fullscreen mode

Your AppDbContext needs to extend PgvectorMemoryDbContext or apply the configuration manually:

public class AppDbContext : PgvectorMemoryDbContext
{
    public AppDbContext(DbContextOptions<PgvectorMemoryDbContext> options)
        : base(options, dimensions: 1536) { }
}
Enter fullscreen mode Exit fullscreen mode

The dimensions parameter must match your embedding model. OpenAI text-embedding-3-small uses 1536. Adjust for other providers.

The HNSW index

The package creates an HNSW index on the embedding column automatically via EF migrations:

entity.HasIndex(e => e.Embedding)
      .HasMethod("hnsw")
      .HasOperators("vector_cosine_ops")
      .HasDatabaseName("IX_Memories_Embedding_Hnsw");
Enter fullscreen mode Exit fullscreen mode

HNSW is approximate nearest neighbour search. It trades a small amount of recall for much faster query times at scale. For memory retrieval this is the right tradeoff. You do not need perfect recall, you need fast and good enough.

When to use which adapter

Use BlazorMemory.Storage.EfCore when:

  • You are building a server-side Blazor or ASP.NET Core app
  • You have a small number of memories per user (under a few hundred)
  • You want the simplest possible setup with SQLite or SQL Server

Use BlazorMemory.Storage.Pgvector when:

  • You are on PostgreSQL already
  • You expect large memory stores per user
  • You want search to scale without loading data into memory

Use BlazorMemory.Storage.IndexedDb when:

  • You are building Blazor WASM
  • You want zero backend
  • Everything stays in the browser

Current state

9 packages on NuGet, 70 tests passing.

GitHub: https://github.com/aftabkh4n/BlazorMemory

Top comments (0)