Markdown Editor

Vector Database System Design Template

Vector search service: HNSW vs IVF-PQ sizing, re-ranking, recall vs latency tuning, filtered search by selectivity, inserts and deletes, sharding, failure modes

SystemdesignVollständigHNSW (Malkov and Yashunin, TPAMI 2020); PQ (Jégou et al., TPAMI 2011)designvectordatabasemath

Anleitung: Use it when designing or choosing a vector database for semantic search, RAG or recommendations. Fill vector count, dimension, query rate and recall target in section 3 first, because memory per vector decides the index family. The main pitfall is trusting benchmark recall instead of measuring it against exact search on your own queries and filters.

Vorschau

System Design: [Vector database name]

Reference design for a vector database that stores embeddings with metadata and answers approximate nearest neighbour (ANN) queries with filters: index choice between HNSW (Malkov and Yashunin, IEEE TPAMI 2020) and IVF with product quantization (Jégou, Douze and Schmid, IEEE TPAMI 2011), filtered search, inserts and deletes on a live index, sharding, replication, and the recall versus latency trade-off. It follows the structure of the System Design Document template, adds a 45-minute interview path, access-pattern and failure-mode tables and a cited "How real systems do it" box, and is pre-filled with a worked design to adapt. Replace every [bracketed] value and every row marked Example; values marked Example are assumptions, not benchmarks. Recall and latency figures must come from your own measurements on your own data.

Document control

FieldValue
Document ID[SDD-VDB-001]
System / feature[Vector search service]
Version[0.1]
Status[Draft / In review / Approved / Implemented / Superseded]
Owner[@owner]
Author(s)[@author]
Reviewers[@reviewer-1], [@reviewer-2]
Last updatedYYYY-MM-DD
Classification[Internal]
DifficultyAdvanced
Embedding model and dimension[Model name, version, d = 768]
Related[RAG design], [Search relevance evaluation], [ADR: index family]

Approvals

RoleNameDecisionDate
Tech lead[@name][Approved / Changes requested]YYYY-MM-DD
Staff / principal engineer[@name][Decision]YYYY-MM-DD
ML / relevance owner[@name][Decision]YYYY-MM-DD
SRE / operations[@name][Decision]YYYY-MM-DD
Security and privacy[@name][Decision]YYYY-MM-DD

Revision history

VersionDateAuthorChange summary
0.1YYYY-MM-DD[@name]First draft for design review
0.2YYYY-MM-DD[@name]Example: Moved the large collection from HNSW to IVF-PQ with re-ranking after the memory estimate
0.3YYYY-MM-DD[@name]Example: Added per-query filter strategy choice by estimated selectivity
1.0YYYY-MM-DD[@name]Example: Approved

Contents

1. Overview

1.1 Problem statement

[Example: Our document assistant stores 500 million passage embeddings in a general-purpose database extension with an HNSW index on one large machine. Memory is at 92%, index rebuilds take two days, and a query filtered to one customer's documents often returns fewer than 10 results because the filter runs after the index search. Deleted documents keep appearing in answers for hours, which is a privacy problem.]

1.2 Proposed solution

[Example: A dedicated vector service shards collections by vector ID across 8 shards with 2 replicas each. Large collections use an IVF index with product-quantized codes in memory and full vectors on local NVMe for re-ranking; small collections use HNSW in memory. Inserts go to a write-ahead log and an in-memory buffer that is searched exactly, then merge into the main index every hour. Deletes are tombstones applied at query time and removed by compaction. Each query picks a filter strategy from the estimated selectivity of its filter. Tenants are separate partitions, so a tenant filter never scans other tenants' data. Recall is measured continuously against exact search on sampled queries.]

1.3 Decisions requested from reviewers

IDQuestionRecommended optionSection
Q-01Example: Index family for the 500-million-vector collection?IVF-PQ with re-ranking from NVMe; HNSW only for collections that fit in memory3, 7.2
Q-02Example: How to filter?Strategy per query from estimated selectivity: pre-filter and exact scan, filtered traversal, or post-filter with over-fetch7.4
Q-03Example: Freshness of inserts and deletes?Visible within 1 s (buffer and tombstones), physically merged hourly7.5
Q-04Example: Sharding key?Hash of vector ID within a tenant partition; queries fan out to all shards7.6
Q-05Example: Recall target and how it is checked?Recall@10 at or above 0.95 against exact search on 1% sampled queries7.3, 9.3
[Q-nn][Question][Option][Section]

1.4 45-minute interview path

Use this order when the document serves an interview or a short design review. The written sections below are the long form of each step.

MinutesCoverOutput on the whiteboard
0 to 5Scope: top-k similarity with filters, inserts and deletes, recall target; below-the-line items (2.3)One query shape and the recall definition
5 to 10Estimates: raw size, HNSW size, PQ size, query fan-out (section 3)Four numbers, "HNSW does not fit in RAM at this scale, so compress and re-rank" consequence
10 to 15API: upsert, delete, query with filter and k (section 4)Three calls
15 to 25High-level design: router, shards with segments, index builder, object storage (section 6)One diagram
25 to 40One deep dive: index choice and recall versus latency (default, 7.2 and 7.3), or filtered search (7.4), or updates and deletes (7.5)Options, choice, reason
40 to 45Failures (shard loss, recall drift after a model change), the 10x row in section 10Two failure rows

Start the default deep dive with the naive answer, exact search (compare the query with every vector). Show its cost: 500 million x 768 multiply-adds per query. Then introduce HNSW, compute its memory, and move to IVF-PQ with re-ranking when the memory does not fit.

2. Requirements

2.1 Core functional requirements

IDRequirementPriority
FR-01Example: Upsert vectors with an ID and metadata (tenant, language, created time, tags)Must
FR-02Example: Query the top k (up to 100) by cosine similarity, with optional metadata filtersMust
FR-03Example: Delete by ID and by filter (all vectors of a document or tenant)Must
FR-04Example: Collections with fixed dimension and metric; one embedding model version per collectionMust
FR-05Example: Hybrid search hook: return scores so a caller can fuse them with keyword resultsShould
FR-06Example: Snapshot and restore a collectionShould
[FR-nn][Requirement][Must / Should / Could]

2.2 Non-functional requirements

IDQualityTargetMeasured as
NFR-01RecallExample: Recall@10 at or above 0.95 against exact searchSampled live queries re-run on the exact path
NFR-02LatencyExample: p99 at or below 50 ms for k = 10 with typical filtersRouter timing
NFR-03ThroughputExample: 2 000 queries/s at peakLoad test
NFR-04FreshnessExample: Upserts and deletes visible to queries within 1 sWrite-then-read probe
NFR-05DurabilityExample: No acknowledged write lostWAL replay test
NFR-06Tenant isolationExample: A query never returns another tenant's vectorPartition audit and tests
[NFR-nn][Quality][Target][Measurement]

2.3 Below the line (out of scope)

Name these explicitly so reviewers and interviewers do not pull the design toward them.

  • [Example: generating embeddings (the caller sends vectors)]
  • [Example: keyword search and rank fusion (see Full-Text Search Engine System Design (system-design/design-full-text-search))]
  • [Example: document chunking and prompt assembly (see Enterprise RAG Search System Design (system-design/design-enterprise-rag-search))]
  • [Example: GPU-based search]
  • [Item deferred, with the release that will take it]

3. Capacity estimation

3.1 Assumptions

InputSymbolValueSource
Vectors in the largest collectionNNExample: 500 millionCorpus size x growth
DimensionddExample: 768, float32Embedding model
Peak queries per secondQQExample: 2 000Product forecast
Inserts per dayIIExample: 5 millionIngestion pipeline
Deletes per dayDdelD_{del}Example: 1 millionDocument lifecycle
HNSW links parameterMMExample: 327.2
PQ sub-quantizers, 8 bits eachmmExample: 96 bytes per vector7.2
Usable memory per nodeUUExample: 179 GB (70% of 256 GB)Instance type
ShardsSSExample: 87.6

3.2 Memory by index family

Raw vectors:

N×d×4=5×108×768×4 B≈1.54 TBN \times d \times 4 = 5 \times 10^{8} \times 768 \times 4 \ \text{B} \approx 1.54 \ \text{TB}

HNSW, using the Faiss wiki estimate of d×4+M×2×4d \times 4 + M \times 2 \times 4 bytes per vector:

5×108×(3 072+256) B≈1.66 TB,1.66 TB179 GB≈9.3⇒10 nodes per replica5 \times 10^{8} \times (3\,072 + 256) \ \text{B} \approx 1.66 \ \text{TB}, \qquad \frac{1.66 \ \text{TB}}{179 \ \text{GB}} \approx 9.3 \Rightarrow 10 \ \text{nodes per replica}

IVF-PQ codes plus an 8-byte ID:

5×108×(96+8) B=52 GB,6.5 GB per shard with S=85 \times 10^{8} \times (96 + 8) \ \text{B} = 52 \ \text{GB}, \qquad 6.5 \ \text{GB per shard with } S = 8

PQ compresses each vector 3 072/96=323\,072 / 96 = 32 times. The full vectors stay on NVMe (192 GB per shard) for re-ranking. Consequence: HNSW for this collection would need 20 large-memory nodes with two replicas; IVF-PQ fits in a fraction of one node's memory per shard, so the cost moves from RAM to NVMe reads.

3.3 Work per query

Each shard holds 62.562.5 million vectors and an IVF with K=262 144K = 262\,144 lists (the Faiss wiki suggests this list count for 10 to 100 million vectors). Probing nprobe=64n_{probe} = 64 lists scans:

62.5×106×64262 144≈15 259 codes per shard,≈122 070 across 8 shards62.5 \times 10^{6} \times \frac{64}{262\,144} \approx 15\,259 \ \text{codes per shard}, \qquad \approx 122\,070 \ \text{across 8 shards}

Each code is scored with a lookup table of 96×256×496 \times 256 \times 4 bytes (about 98 KB per query per shard). Each shard then re-ranks its best 100 candidates with full vectors read from NVMe: 100 reads of 3 KB, one 4 KB page each. With 2 replicas sharing the 2 000 queries/s:

1 000×100=105 random reads/s per replica≈0.41 GB/s1\,000 \times 100 = 10^{5} \ \text{random reads/s per replica} \approx 0.41 \ \text{GB/s}

That is within one data-centre NVMe drive's random-read capability, but not with much headroom, which is why re-rank depth is a tuning knob in 7.3.

3.4 Writes

Inserts average 5×106/86 400≈585 \times 10^{6} / 86\,400 \approx 58 per second (about 7.2 per shard) and deletes about 12 per second. An hour of inserts per shard is about 26 042 vectors (80 MB), which an exact scan covers in about 2 ms at an assumed 20 GFLOP/s, so a flat buffer is enough for fresh data (7.5).

3.5 Summary

QuantityEstimateDesign consequence
Raw vectors1.54 TBStored on NVMe and object storage, not in RAM
HNSW in memory1.66 TB (about 10 nodes per replica)Used only for collections that fit in memory
IVF-PQ codes52 GB total, 6.5 GB per shardLarge collection uses IVF-PQ
Re-rank reads100 000 random reads/s per replicaNVMe per node, re-rank depth tuned
Insertsabout 58/sFlat buffer plus hourly merge

4. API design

4.1 Endpoints

Method and pathPurposeNotes
PUT /v1/collections/{c}Create a collection with dimension, metric, model version and index profileDimension and metric immutable
POST /v1/collections/{c}/upsertInsert or replace up to 1 000 vectorsReturns a write sequence number
POST /v1/collections/{c}/deleteDelete by IDs or by filterReturns a write sequence number
POST /v1/collections/{c}/queryTop-k with filter and search parametersOptional min_seq for read-your-writes
POST /v1/collections/{c}/snapshotsCreate a snapshotStored in object storage

Errors use problem details (RFC 9457). A query with a vector of the wrong dimension returns 400; a query against a collection whose model version differs from the caller's declared version returns 409.

4.2 Query example

{"vector": [0.0132, -0.0871, 0.0419], "k": 10, "filter": {"and": [{"tenant": {"eq": "t_2207"}}, {"lang": {"in": ["en", "de"]}}, {"created_at": {"gte": "2026-01-01"}}]}, "params": {"nprobe": 64, "rerank": 100}, "min_seq": 88412093, "include": ["score", "metadata"]}

The vector is shortened here to three values; a real request carries all 768.

{"results": [{"id": "doc-7731#p4", "score": 0.8412, "metadata": {"lang": "en"}}, {"id": "doc-0918#p1", "score": 0.8377, "metadata": {"lang": "de"}}], "strategy": "filtered_traversal", "shards": 8, "took_ms": 23}

5. Data model

5.1 Entities

A collection is split into partitions (one per tenant), each partition into shards, and each shard into segments: one growing buffer and several sealed, indexed segments.

5.2 Storage choices

DataStoreKeyWhy
Write-ahead logExample: Replicated log, one partition per shardSequence numberDurability before acknowledgement, replay after crash
PQ codes and IVF listsShard memory, persisted to local disk and object storageList ID, then vector IDScanned on every query
Full vectorsLocal NVMe, copy in object storageVector ID to page offsetRe-ranking reads
Metadata and filter indexesColumnar per segment with bitmap and range indexesVector IDFast bitmap for any filter
TombstonesBitmap per segmentRow offsetApplied at search, cleared at compaction
Catalog (collections, shards, segments)Example: Consensus-backed metadata storeCollection IDSmall, strongly consistent

5.3 Access patterns

Access patternFrequencyKey or index that serves itPartition key rationale
Top-k query with tenant filter2 000/s at peakTenant partition, then IVF lists on every shardTenant partition removes other tenants' data before any distance is computed
Top-k with a selective metadata filterPart of the aboveSegment bitmap index on the filtered fieldsSelectivity estimate picks the strategy (7.4)
Upsertabout 58/sWAL by shard (hash of vector ID)Hashing spreads writes and sizes evenly
Delete by IDabout 12/sVector ID to segment and row lookupSame shard as the insert
Delete a whole document or tenantRareMetadata index, or drop the tenant partitionDropping a partition is instant and certain
Rebuild or compact a segmentHourly to weeklySegment IDSegments are the unit of rebuild

6. High-level design

ComponentResponsibilityScales by
Query routerFan out to all shards of the partition, merge top-k, enforce timeoutsStateless instances
Filter plannerEstimate selectivity, choose strategy and search parametersIn router
Write API and WALValidate, assign sequence number, persist before acknowledgingLog partitions per shard
Shard replicaApply WAL, keep buffer and segments, answer local top-kShards and replicas
Index builder and compactorMerge buffers into the main index, remove tombstoned rows, retrain when neededBackground workers
CatalogCollections, shard map, segment list and versionsConsensus group

7. Detailed design

The deep dives in this section, each with options, choice and reason:

Deep diveOptions consideredChoiceReasonSection
Index familyExact (flat); HNSW; IVF-flat; IVF-PQ with re-rank; disk-based graphIVF-PQ with re-rank for large, HNSW for smallMemory at 500 million vectors7.2
Recall versus latencyFixed parameters; per-collection tuning; per-query budgetPer-collection profile with per-query overrideDifferent collections, different trade-offs7.3
FilteringPost-filter; pre-filter and exact scan; filtered traversal; partitioningPlanner chooses by selectivity; tenants as partitionsNo single strategy wins across selectivities7.4
UpdatesRebuild index; in-place insert; buffer and mergeBuffer, tombstones, hourly merge, compactionFreshness without index churn7.5

7.1 Exact search as the baseline

Exact search compares the query with every vector. For one shard of 62.5 million vectors at d=768d = 768 that is about 62.5×106×768×2≈9662.5 \times 10^{6} \times 768 \times 2 \approx 96 GFLOP per query, seconds of CPU time. It stays in the design for two jobs: searching the small growing buffer, and producing the ground truth that recall is measured against (NFR-01).

7.2 Index families

FamilyHow it worksMemory per vector at d=768d = 768UpdatesFits
Flat (exact)Scan all vectors3 072 BTrivialSmall sets, ground truth
HNSWLayered proximity graph; greedy search from the top layer down3 328 B with M=32M = 32Inserts incremental; deletes need tombstones (the Faiss wiki notes HNSW cannot remove vectors)Collections that fit in RAM; lowest latency at high recall
IVF-flatk-means lists; scan the closest nproben_{probe} lists3 072 B + IDInserts go to the nearest listMemory somewhat constrained
IVF-PQ plus re-rankLists of compressed codes; re-rank the best candidates with full vectors104 B in RAM, 3 072 B on NVMeInserts encode with the trained codebooksHundreds of millions of vectors
Disk-based graph (DiskANN family)Graph and full vectors on SSD, compressed vectors in RAMCompressed codes in RAMSupported with careBillion scale per node

HNSW in brief (Malkov and Yashunin, 2020): each vector gets a random top layer drawn with an exponentially decaying probability; with the usual normalisation mL=1/ln⁡Mm_L = 1/\ln M, the share of vectors that reach layer 1 or above is 1/M1/M (about 3.1% for M=32M = 32), and the number of layers grows with ln⁡N/ln⁡M\ln N / \ln M, about 5.2 for one shard of 62.5 million vectors. Search starts at the top layer and descends greedily, then explores efSearch candidates on the bottom layer. Larger efSearch gives higher recall and higher latency.

Product quantization in brief (Jégou, Douze and Schmid, 2011): the vector is split into mm sub-vectors, each replaced by the index of its nearest centroid in a 256-entry codebook, so a 768-dimension float vector becomes 96 bytes. Distances to a query are computed from a per-query lookup table (asymmetric distance computation), which is why the codes never need to be decompressed. PQ distances are approximate, so the best candidates are re-ranked with the full vectors.

Choice: the 500-million-vector collection uses IVF with K=262 144K = 262\,144 lists per shard, PQ with 96 bytes per vector, and re-ranking of 100 candidates per shard from NVMe. Collections under about 20 million vectors (about 67 GB in HNSW) use HNSW in memory. Training needs at least 30×K≈7.930 \times K \approx 7.9 million sample vectors per shard (Faiss wiki guidance of 30 to 256 times the list count); the codebooks are trained once per collection version.

7.3 Recall versus latency

Three knobs move the trade-off: nproben_{probe} (lists scanned), re-rank depth, and for HNSW efSearch. Fill the measured columns from your own benchmark with the exact path as ground truth:

nproben_{probe}Codes scanned per shardCodes scanned in totalRecall@10p99 latency
163 81530 518[measure][measure]
327 62961 035[measure][measure]
64 (default)15 259122 070[measure][measure]
12830 518244 141[measure][measure]

Pick the smallest setting that meets NFR-01 on the 5th percentile of per-query recall, not only the mean: average recall can hide a class of queries (for example short queries or a rare language) that fail badly. Re-check after every embedding model change, every codebook retrain and every large shift in the data.

7.4 Filtered search

With filter selectivity ss (the share of vectors that pass), a post-filter must fetch about k/sk/s candidates to keep kk results. For NN = 500 million and 8 shards:

Selectivity ssCandidates for k=10k = 10 with post-filterMatching vectors per shardExact scan of matches per shard (at 20 GFLOP/s)Strategy
0.52031 250 000far too slowPost-filter with small over-fetch
0.11006 250 000far too slowFiltered traversal (bitmap checked during search)
0.011 000625 00048 msFiltered traversal, larger nproben_{probe}
0.00110 00062 5004.8 msPre-filter by bitmap, then exact scan

The planner estimates ss from per-segment field statistics and picks the strategy; the response reports which one ran so slow queries can be explained. Graph indexes lose connectivity when most nodes fail the filter, which is why research such as Filtered-DiskANN (WWW 2023) and ACORN (SIGMOD 2024) builds filter awareness into the graph. Tenants are never a filter: each tenant is a partition, so the most common and most important filter costs nothing and cannot leak (NFR-06).

The thresholds 0.002 and 0.3 are Example values; set them from a benchmark on your data.

7.5 Inserts, deletes and freshness

  1. An upsert is written to the shard's WAL and acknowledged with its sequence number.
  2. Each replica applies the WAL to its growing buffer (flat, searched exactly) within 1 s. A replaced ID gets a tombstone in its old segment.
  3. Every hour the builder encodes the buffer (about 26 000 vectors per shard) with the existing codebooks and appends the codes to their IVF lists in a new segment version; the buffer is then cleared. Queries switch to the new version atomically.
  4. A delete sets a tombstone bit immediately, so the vector disappears from results within 1 s (NFR-04). Compaction rewrites a segment when its deleted share passes 20%; at 1 million deletes a day spread evenly over 500 million vectors that takes about 100 days, but deleting a tenant drops its partition at once.
  5. Codebooks are retrained when recall on the sampled queries drifts below target, by building a new collection version in the background.

min_seq gives read-your-writes: a replica that has not applied that sequence number waits up to 200 ms or the router tries another replica.

7.6 Sharding and replication

Vectors are assigned to shards by hash of their ID inside each tenant partition, so every shard holds a similar slice of every large tenant and queries fan out to all shards. Fan-out multiplies the work per query, but it keeps shard sizes even and lets any shard answer for any query. Each shard has 2 replicas behind the router; the router sends each query to one replica per shard, hedges after the shard's p95 latency, and merges the top-k lists. The tail latency of a query is the slowest shard's latency, so per-shard p99 must sit well below the end-to-end target.

7.7 How real systems do it

How real systems do it (paraphrased, not copied). The Milvus paper (Wang and others, "Milvus: A Purpose-Built Vector Data Management System", SIGMOD 2021) describes inserts held in memory and flushed as immutable segments when a size threshold is reached or every second, small segments merged into larger ones under a tiered policy, deletes handled out of place and removed at merge time, and indexes built only for large segments. Each query runs on a snapshot of the current segments, so writes do not disturb running queries. For attribute filters the paper compares attribute-first scans, attribute bitmaps checked during vector search, vector-first search followed by an attribute check, and a cost-based choice between them, and adds a partition-based method on frequently filtered attributes that its experiments found faster than the cost-based one. The Faiss wiki "Guidelines to choose an index" gives the memory estimate used in 3.2 and list-count guidance by dataset size. Read the originals in 12.3; this box keeps only the general ideas.

8. Scalability and performance

ConcernApproachLimit before redesign
Query rateAdd replicas per shardNVMe random reads for re-rank (3.3)
Collection sizeAdd shards; codes are 104 B per vectorTraining time for codebooks and list count
Fan-out tail latencyHedged requests, per-shard timeouts, partial results flaggedAbout 32 shards before tail latency dominates
FiltersPlanner and bitmap indexesFilters on high-cardinality fields without statistics
WritesWAL per shard, hourly mergeMerge time once buffers exceed an hour of inserts

Latency budget for a query (target p99 50 ms):

StepBudget
Router, planner, fan-out3 ms
Coarse quantizer and list scan per shard12 ms
Re-rank (100 NVMe reads in parallel)8 ms
Growing buffer exact scan2 ms
Merge across shards and return3 ms
Headroom for the slowest shard22 ms

9. Reliability, security and operations

9.1 Failure modes

ComponentFailureDetectionBlast radiusMitigationRTO
Shard replicaNode lostHealth checkHalf the capacity of one shardRouter uses the other replica; rebuild from object storage and WALExample: 20 min to restore the replica
Both replicas of a shardLost togetherRouter errorsOne eighth of results missingReturn partial results flagged partial: true; restore from snapshotExample: 30 min
NVMe driveSlow or failingRe-rank latency per nodeOne replicaDrain node; skip re-rank and serve PQ-only results with a flagExample: 5 min
Index builderMerge failsBuffer age above 2 hBuffer grows, query latency risesAlert; buffer is still searched exactlyExample: 1 h
Embedding modelNew version mixed with oldModel version check on queryWrong neighbours across the collectionCollection pinned to one model version; new version is a new collectionExample: immediate rejection
RecallDrift after data shiftSampled recall below targetAnswer qualityRaise nproben_{probe} temporarily; retrain codebooksExample: 1 day
[Component][Failure][Signal][Scope][Mitigation][Time]

9.2 Security and privacy

ThreatControl
Cross-tenant leakageTenant partitions; tenant taken from the authenticated principal, never from the request body
Deleted personal data still retrievableTombstones within 1 s; compaction and snapshot expiry documented for erasure requests
Embedding inversion (reconstructing text from vectors)Treat vectors as sensitive as the source text; encrypt at rest; restrict raw vector export
Abuse of expensive queriesCaps on k, nproben_{probe} and filter complexity per tenant; per-tenant rate limits

9.3 Observability

SignalMetric or logAlert threshold
RecallRecall@10 on 1% sampled queries re-run exactlyBelow 0.95 for 1 h
Latencyp99 end to end and per shardAbove 50 ms for 10 min
Filter strategy mixShare of queries per strategySudden shift
FreshnessWrite-to-visible probeAbove 1 s
Buffer and tombstonesBuffer age, deleted share per segmentBuffer older than 2 h

9.4 Cost estimate

ItemUnit costQuantityMonthly cost
Shard nodes with NVMe[$/node-month]Example: 16[$]
Router instances[$/instance-month]Example: 6[$]
Object storage for segments and snapshots[$/GB-month]Example: 3 TB[$]
Re-embedding a collection[$/GPU-hour]Example: 28 GPU-hours for 500 million vectors at 5 000/s per GPU[$]
Total[$]

10. Trade-offs and alternatives

DecisionOptionsChosenWhyWhat we give up
Index for large collectionHNSW in RAM; IVF-PQ with re-rank; disk graphIVF-PQ with re-rank52 GB of codes instead of 1.66 TB of graphHigher latency than HNSW at the same recall; training step
DatabaseVector extension in the main relational database; dedicated serviceDedicated serviceScale and index controlSecond system to operate; joins with business data are the caller's job
FilteringOne strategy; planner per queryPlanner per querySelectivity varies by orders of magnitudePlanner needs statistics and testing
FreshnessRebuild nightly; buffer and mergeBuffer and mergeVisible within 1 sMerge machinery and tombstones
ShardingBy tenant; by hash of IDHash within tenant partitionsEven shards, any tenant sizeFan-out to every shard
What changes at 10x / 0.1x10x (5 billion vectors): 520 GB of codes and 15.4 TB of full vectors, about 80 shards at today's 6.5 GB of codes each, so fan-out tail latency forces a two-level route (coarse routing to a subset of shards) or a disk-based graph per node. 0.1x (50 million vectors): about 166 GB in HNSW, above the 20-million HNSW limit in 7.2 and 93% of one node's usable memory, so either HNSW across 2 shards or IVF-PQ in one shard (5.2 GB of codes) with no fan-outReview at each doubling of vectorsMemory and fan-out grow first[Note]
[Decision][Options][Chosen][Why][Cost]

11. Delivery plan and risks

11.1 Milestones

MilestoneScopeExit criterionTarget date
M1Exact path, WAL, buffer, ground-truth harnessRecall harness reports on sampled queriesYYYY-MM-DD
M2IVF-PQ shards with re-rank, shadow trafficRecall@10 at or above 0.95 and p99 at or below 50 ms in shadowYYYY-MM-DD
M3Filter planner, tenant partitionsNo cross-tenant result in audit; filtered recall at targetYYYY-MM-DD
M4Cutover, deletes within 1 s, compactionErasure test passes end to endYYYY-MM-DD

11.2 Rollout and rollback

[Example: Dual-write to the old and new stores, compare top-10 overlap on shadow queries for 14 days, then move read traffic per tenant in steps. Rollback points reads back to the old store while dual writes continue.]

11.3 Risks

IDRiskLikelihoodImpactMitigationOwner
R-01Example: Recall on real queries lower than on the benchmark setMediumHighSample live queries for the harness from day one[@name]
R-02Example: Embedding model upgrade forces full re-indexHighMediumCollection per model version; re-embedding budget planned[@name]
R-03Example: NVMe read rate becomes the bottleneckMediumMediumRe-rank depth tuning; more replicas[@name]
[R-nn][Risk][L / M / H][L / M / H][Mitigation][@name]

12. Appendices

12.1 Open questions

IDQuestionOwnerDue
OQ-01Example: Do we need multi-vector documents (one vector per passage, results grouped by document)?[@name]YYYY-MM-DD
OQ-02Example: Is a disk-based graph worth evaluating before 10x?[@name]YYYY-MM-DD
[OQ-nn][Question][@name]YYYY-MM-DD

12.2 Glossary

TermMeaning
ANNApproximate nearest neighbour search: trades exactness for speed
Recall@kShare of the true top-k (from exact search) that the approximate search returns
HNSWHierarchical navigable small world graph index
IVFInverted file index: vectors grouped into lists by nearest k-means centroid
PQProduct quantization: vectors compressed into codes of sub-vector centroid indexes
nproben_{probe}Number of IVF lists scanned per query
efSearchHNSW candidate list size during search
TombstoneMark that hides a deleted vector until compaction removes it
SelectivityShare of vectors that pass a filter
[Term][Meaning]

12.3 References

ReferenceUse
Malkov, Y. A. and Yashunin, D. A. "Efficient and Robust Approximate Nearest Neighbor Search Using Hierarchical Navigable Small World Graphs", IEEE TPAMI 42(4), 824 to 836, 2020, doi:10.1109/TPAMI.2018.2889473HNSW in 7.2
Jégou, H., Douze, M. and Schmid, C. "Product Quantization for Nearest Neighbor Search", IEEE TPAMI 33(1), 117 to 128, 2011, doi:10.1109/TPAMI.2010.57PQ in 7.2
Douze, M. and others. "The Faiss Library", IEEE Transactions on Big Data 12(2), 346 to 361, 2026, doi:10.1109/TBDATA.2025.3618474Index families
Faiss wiki, "Guidelines to choose an index", checked 2026-10-30Memory formula in 3.2, list counts in 3.3 and 7.2
Wang, J. and others. "Milvus: A Purpose-Built Vector Data Management System", SIGMOD 2021, 2614 to 2627, doi:10.1145/3448016.34575507.5, 7.7
Subramanya, S. J. and others. "DiskANN: Fast Accurate Billion-point Nearest Neighbor Search on a Single Node", NeurIPS 2019Disk-based graph in 7.2
Gollapudi, S. and others. "Filtered-DiskANN: Graph Algorithms for Approximate Nearest Neighbor Search with Filters", WWW 2023, doi:10.1145/3543507.35835527.4
Patel, L., Kraft, P., Guestrin, C. and Zaharia, M. "ACORN: Performant and Predicate-Agnostic Search Over Vector Embeddings and Structured Data", Proceedings of the ACM on Management of Data 2(3) (SIGMOD 2024), 2024, doi:10.1145/36549237.4
Enterprise RAG Search System Design (system-design/design-enterprise-rag-search)Main consumer of this service
RAG System Design (ai-data/rag-system-design)Retrieval quality and evaluation
Full-Text Search Engine System Design (system-design/design-full-text-search)Keyword side of hybrid search
Recommendation System Design (system-design/design-recommendation-system)Candidate retrieval by embeddings
Back-of-Envelope Estimation and Capacity Model (system-design/back-of-envelope-estimation)Method for section 3

Standard and licence note

Based on the published research cited in 12.3 (HNSW, product quantization, filtered ANN search, the Milvus and Faiss papers) and on common industry practice for vector search services. No standard governs this design. The papers and the Faiss wiki are paraphrased only; no text, figures or code were copied. Capacity figures are computed from the stated example inputs, and recall and latency must be measured on your own data. Original text written for this collection. Template licence: MIT.

Ähnliche Vorlagen