.NETRAGEmbeddingsArchitecture

Choosing a Vector Database for .NET: pgvector vs Qdrant vs Azure AI Search vs SQL Server

A practical comparison of the vector stores .NET can talk to — pgvector, Qdrant, Azure AI Search, SQL Server 2025, Redis, Cosmos DB and SQLite — and why the choice matters less than you think.

Every RAG project reaches the same fork: where do the vectors go? The internet will happily sell you a benchmark showing one store beating another by 15% on recall at some QPS, and that number will almost certainly not be the thing that decides your project.

Here is what actually decides it, and then the honest comparison.

First: the choice is more reversible than it feels

Microsoft.Extensions.VectorData gives .NET a single abstraction over vector stores, the same way IDistributedCache did for caching. Your record model is attributed once:

public sealed class DocChunk
{
    [VectorStoreKey]
    public Guid Id { get; set; }

    [VectorStoreData(IsIndexed = true)]
    public string SourceDocument { get; set; } = "";

    [VectorStoreData]
    public string Text { get; set; } = "";

    [VectorStoreVector(Dimensions: 1536)]
    public ReadOnlyMemory<float> Embedding { get; set; }
}

And your query code targets the abstraction, not the vendor:

VectorStoreCollection<Guid, DocChunk> chunks = /* connector-specific construction */;

await chunks.EnsureCollectionExistsAsync();
await chunks.UpsertAsync(chunk);

await foreach (var result in chunks.SearchAsync(queryEmbedding, top: 5))
{
    Console.WriteLine($"{result.Score:F3}  {result.Record.Text}");
}

Swapping stores changes the construction line and the NuGet package. It does not change your ingest pipeline, your record shape, or your retrieval code.

One caveat to be precise about: the abstractions package is GA, while several of the connector implementations still ship as preview packages. That is fine for most teams, but if your organisation has a hard “no preview packages in production” rule, check the specific connector you want before you plan around it.

The practical consequence: do not spend three weeks choosing. Pick the one that fits your operations today, ship, and revisit if you outgrow it. What you cannot recover cheaply is not the code — it is the re-embedding cost of moving a large corpus, so size that before you commit at scale.

The comparison

.NET has connectors for Azure AI Search, Qdrant, Redis, PostgreSQL, Azure Cosmos DB (NoSQL), SQL Server, SQLite and an in-memory store. That is the realistic menu.

Store Pick it when Watch out for
In-memory Prototypes, tests, corpora under ~10k chunks Rebuilt on every restart; no persistence
SQLite Desktop apps, single-node services, edge Single-writer; not for a scaled-out web tier
PostgreSQL + pgvector You already run Postgres. The default answer. Index tuning matters past a few million vectors
SQL Server 2025 Your data is already in SQL Server ANN index (DiskANN) still preview-gated
Azure AI Search Azure shop; you need hybrid keyword + vector Cost at scale; a service to provision and manage
Qdrant Tens of millions of vectors, heavy metadata filtering Another system to run, monitor and back up
Redis You already run Redis and want low-latency lookup Memory-resident cost model at large index sizes
Cosmos DB (NoSQL) You are already on Cosmos and need global distribution RU-based cost modelling takes real effort

PostgreSQL + pgvector — the default

If you have no strong reason to do otherwise, this is the answer, and the reason is not technical excellence. It is that your vectors live next to your relational data.

That means one connection story, one backup, one failover plan, one on-call runbook. It means you can join a similarity search to Documents and Permissions in a single query, which matters enormously the moment you need per-user access filtering on retrieval — a requirement that shows up in almost every enterprise RAG project and is genuinely awkward when your vectors live in a separate system.

Performance is not the constraint people assume. With an HNSW index, pgvector serves hundreds of thousands to a few million vectors comfortably on ordinary hardware. It starts to struggle when you combine tens of millions of vectors with high QPS and heavy metadata filtering — a real ceiling, but far above where most corpora sit. We have a full setup walkthrough in using pgvector from .NET.

SQL Server 2025 — the one that changed the calculus

This is genuinely new and under-discussed. SQL Server 2025 ships a native VECTOR data type and VECTOR_DISTANCE function, both generally available. For the very large population of .NET shops whose data already lives in SQL Server, “add a column” now beats “add a database”.

SELECT TOP (5) Id, Text,
       VECTOR_DISTANCE('cosine', Embedding, @query) AS Distance
FROM   DocChunks
ORDER  BY Distance;

That query does an exact scan. For approximate nearest-neighbour search you want the DiskANN-backed vector index and the VECTOR_SEARCH function — and those are still in preview, behind the PREVIEW_FEATURES configuration. So the honest framing is: exact search over a moderate corpus is production-ready today; large-scale ANN is a “validate it yourself first” proposition. Half-precision vectors and dimensions up to roughly 4,000 are supported, which covers every mainstream embedding model.

Azure AI Search — when you need hybrid retrieval

The reason to choose Azure AI Search is rarely the vector index. It is that pure vector search is often worse than you expect on exact-match queries — product codes, error numbers, person names, acronyms. Embeddings are good at meaning and mediocre at literal strings, so a user searching “ORA-01555” gets semantically-similar-but-wrong results.

Hybrid search — vector plus BM25 keyword, fused and reranked — fixes that class of failure, and Azure AI Search gives it to you as a managed feature rather than something you assemble. If your corpus has a lot of identifiers, part numbers or names in it, that alone can justify the choice.

The counterweight is cost. It is a provisioned service billed on tier and replicas, not on rows, and it is easy to over-provision early. Model it at your real index size.

Qdrant — when you have actually outgrown the others

Qdrant is a purpose-built vector engine, and it is very good at the thing that breaks the general-purpose options: large-scale search with heavy metadata filtering. If you are filtering every query by tenant, document type, date range and permission set across tens of millions of vectors, this is where the specialised engine pulls ahead decisively.

Below that scale, you are taking on a second datastore — its own deployment, monitoring, backups, upgrades and on-call surface — to solve a problem you do not have yet. That is a real cost, paid by the team that operates it.

If you are running it locally during development, Aspire makes that painless — see orchestrating a local AI stack with .NET Aspire.

Redis, Cosmos DB, SQLite — situational

Redis makes sense when you already run it and want retrieval latency in the low milliseconds. It is memory-resident, so the cost model bites at large index sizes.

Cosmos DB (NoSQL) makes sense when you are already on Cosmos and need its global distribution. Budget real time for RU-based cost modelling.

SQLite is underrated for desktop and edge scenarios — a .db file that ships with your app and needs no server at all. The GA API makes this a two-line setup:

VectorStoreCollection<int, Product> collection =
    new SqliteCollection<int, Product>(
        connectionString: "Data Source=products.db",
        name: "products",
        new SqliteCollectionOptions { EmbeddingGenerator = embeddingGenerator });

Note EmbeddingGenerator on the options: the collection can generate embeddings for you on upsert and search, so you pass text and never touch a float[].

Start smaller than you think

The mistake I see most often is provisioning a vector database on day one for a corpus of 4,000 chunks. Four thousand chunks of 1,536-dimension floats is about 25 MB. That fits in memory with room to spare.

A defensible progression:

  1. In-memory while you are still changing your chunking strategy weekly — and you will be, because chunking affects answer quality far more than store choice does.
  2. Whatever database you already run — pgvector or SQL Server 2025 — once the corpus needs to survive restarts.
  3. A dedicated engine only when you have a measured problem the general-purpose option cannot solve.

Skipping straight to step 3 buys you operational burden in exchange for headroom you are not using.

The decision, in four questions

  1. Under ~10k chunks and still iterating? In-memory. Add nothing.
  2. Already run PostgreSQL or SQL Server 2025? Use it. Same backup, same failover, same on-call.
  3. Corpus full of identifiers, part numbers or names? Azure AI Search, for hybrid retrieval — the accuracy gain is the real reason, not the hosting.
  4. Tens of millions of vectors with heavy per-query filtering, measured? Qdrant.

If none of those clearly applies, take option 2 and move on to the work that actually determines answer quality: chunking, retrieval evaluation, and prompt grounding.

Takeaway

Vector store choice gets over-thought because it looks like an architectural decision, when the abstraction layer has made it closer to a configuration one. Pick the database your team already operates, keep your code on VectorStoreCollection<TKey, TRecord> so the door stays open, and spend the time you saved on chunking and retrieval evaluation — those move answer quality by far more than any index will. Two things genuinely justify a specific choice: hybrid search when your content is full of literal identifiers, and filtered search at tens of millions of vectors. Everything else is a tie, and ties should go to the system you already know how to run at 3am.


Have a correction or a topic you want covered? Email mani.bc72@gmail.com.

Frequently asked questions

What is the best vector database for .NET?

The one your team already operates. Because Microsoft.Extensions.VectorData abstracts the store behind VectorStoreCollection<TKey, TRecord>, the decision is reversible, so operational familiarity beats benchmark scores. If you already run PostgreSQL, use pgvector. Already on Azure and need hybrid search, use Azure AI Search. Running SQL Server 2025, use its native VECTOR type. Only reach for a dedicated store like Qdrant when scale or filtering demands it.

Is pgvector good enough for production?

For the large majority of corpora, yes. pgvector with an HNSW index handles hundreds of thousands to a few million vectors comfortably on ordinary hardware, and you get transactions, joins to your relational data, and one backup story instead of two. Its practical ceiling is high-QPS filtered search at tens of millions of vectors, which is where a purpose-built engine starts to earn its keep.

Do I need a vector database at all?

Not always. Below roughly ten thousand chunks, an in-memory store rebuilt at startup is genuinely fine and removes an entire piece of infrastructure. Start there, measure, and add a real store when the index stops fitting comfortably in memory or you need it to survive restarts.

Can I switch vector stores later without rewriting my app?

Largely, yes — that is the point of the Microsoft.Extensions.VectorData abstractions. Your record model and query code stay the same; the connector registration changes. What does not carry over is the data, so a switch still means re-embedding or exporting and re-indexing your corpus.

What about SQL Server 2025 vector search?

SQL Server 2025 ships a native VECTOR data type and VECTOR_DISTANCE function that are generally available, which makes it a strong choice if your data already lives there. The DiskANN-backed vector index and VECTOR_SEARCH function for approximate nearest-neighbour search are still in preview and gated behind PREVIEW_FEATURES, so validate that part against your own workload before you depend on it.