Chapter 17 · Vector Search: Embeddings, KNN Indexes, Distance Measures, Filters, and Retrieval Design
Create / Manage Firestore Vector Indexes and Understand Supported Dimensions / Query Limits
Create and reason about Firestore vector indexes, flat-index mechanics, 2,048-dimension limits, Standard Core query limits, composite prefilters, index lifecycle, and emulator/production gaps.
1. AtlasMart problem: a correct vector can still be unqueryable without the right managed index
Use the Emulator Suite, a Firebase demo project, or an isolated test project for destructive, security-sensitive, billing-sensitive, migration, backup/restore, or write-heavy exercises unless the lesson explicitly marks managed verification as required. Treat shown output as expected evidence unless it is explicitly identified as captured output, and re-check current Firebase/Google Cloud edition, mode, quota, pricing, and security documentation before production execution.
The local oracle can rank six vectors without Firestore, but managed KNN depends on a vector index whose field, dimension and prefilter fields match the query shape. AtlasMart needs an index lifecycle that is reviewable and deployable, not an “error message → click create → forget” ritual.
AtlasMart continues the same canonical lab environment used in
Chapters 01–16: project ID
demo-atlasmart-firestore, Standard edition /
Native mode / (default) database, Firestore
emulator 127.0.0.1:8080, Authentication emulator
127.0.0.1:9099, Emulator UI
127.0.0.1:4000, Firebase JavaScript SDK
12.19.0, Firebase Admin Node.js SDK
14.4.0 carrying
@google-cloud/firestore 9.1.0,
@firebase/rules-unit-testing 5.0.2,
Firebase CLI 15.30.0, and Node.js 22+. Mandatory
work is local/no-cost. Managed vector indexes, managed KNN
billing, production latency, Query Explain, Enterprise
Pipeline execution, and external embedding services are
optional bounded exercises only.
The emulator is suitable for AtlasMart documents, Security
Rules, deterministic fixture management, and local application
tests, but it does not enforce production
composite/vector-index requirements and cannot certify managed
vector-query latency, index-build status, billing,
availability, or Enterprise execution. Therefore the mandatory
lab stores deterministic vectors as ordinary numeric arrays
and runs an exact local KNN oracle; the lesson also shows the
real managed gcloud/@google-cloud/firestore
commands, clearly labeled as optional production/demo-project
steps.
Learning outcomes
Create a Standard Native flat vector index with the exact vector dimension.
Explain why metadata prefilters require a composite vector index.
Distinguish index build readiness from query correctness and from retrieval quality.
Apply the Standard 2,048-dimension and 1,000-result limits only where documented.
Avoid using emulator success as proof that a production index exists.
2. Flat is the current Standard Native vector-index type
Current Firestore vector-search documentation requires
flat for the vector configuration. The index
dimension must match the stored/query vector dimension.
AtlasMart’s teaching fixture uses dimension 8; a production
model can use another supported dimension up to 2,048. Choosing
a smaller fixture does not imply a tuning recommendation.
# Optional managed Standard Native exercise; billing/real project may be required.gcloud components updategcloud firestore indexes composite create \ --collection-group=vectorProducts \ --query-scope=COLLECTION \ --field-config=order=ASCENDING,field-path="tenantId" \ --field-config=order=ASCENDING,field-path="category" \ --field-config=field-path="embeddingV1",vector-config='{"dimension":"8","flat":"{}"}' \ --database='(default)'# Inspect current indexes in the selected project/database before querying.gcloud firestore indexes composite list --database='(default)'
3. Index shape follows the retrieval contract
A single-field vector index is enough for an unfiltered KNN
search on one collection. If AtlasMart must first constrain by
tenantId and category, the index needs
those scalar fields plus the vector field. The filter reduces
the candidate population before nearest-neighbor evaluation,
which improves isolation and can reduce scanned work, but only
if application authorization guarantees the filter cannot be
broadened by an untrusted caller.
| Query contract | Index | Failure if mismatched |
|---|---|---|
KNN on embeddingV1 |
Vector field, dimension 8, flat | Missing-index error / cannot execute managed query |
tenantId == A + KNN |
tenantId + vector |
Composite vector index required |
tenantId == A +
category == cameras + KNN
|
Both scalar prefilter fields + vector | Query/index contract incomplete |
| Index dimension 8, query vector dimension 7 | Invalid | Reject before sending; dimension mismatch is a schema error |
4. Index readiness is operational state
Index creation is asynchronous. Treat “command accepted” and “index ready” as separate states. A release that depends on a new vector index should verify readiness before shifting traffic. If the index is missing, Firestore can suggest a creation command; that suggestion is useful, but the application still needs reviewable infrastructure ownership and rollback instructions.
export function validateSearchContract({ vector, expectedDimension, modelVersion }) { if (!Array.isArray(vector) || vector.length !== expectedDimension) { throw new Error(`dimension mismatch: expected ${expectedDimension}, got ${vector?.length}`); } if (modelVersion !== 1) throw new Error(`unsupported embeddingVersion ${modelVersion}`); if (vector.some(v => !Number.isFinite(v))) throw new Error("non-finite vector value"); return true;}validateSearchContract({ vector:[0,0,0,0,0,0,0,0], expectedDimension:8, modelVersion:1 });
5. Standard Core limits that change design
Current Standard Native documentation caps an embedding at 2,048 dimensions and a nearest-neighbor query at 1,000 returned documents. It also documents no realtime snapshot listeners for vector queries and server-library support in Python, Node.js, Go and Java. Those are implementation boundaries, not reasons to request 1,000 neighbors. K should be chosen from product needs and quality evaluation.
Enterprise Native Pipeline has a distinct
findNearest stage and broader documented
SDK/client surface. Its stage options and pricing model are
not defined by the Standard Core page. Chapter 18 studies that
execution model separately.
6. Emulator trap: “the query worked locally” is not an index test
The Firestore emulator does not enforce production
composite-index requirements. Therefore an emulator query
succeeding without firestore.indexes.json or a
managed vector index does not prove the production query can
run. Use the emulator for data/rules/application tests, and an
isolated managed project for index-readiness tests when release
risk justifies it.
7. Optional managed Node.js query
import { Firestore, FieldValue } from "@google-cloud/firestore";const db = new Firestore({ projectId: process.env.GCLOUD_PROJECT });const q = [0.90,0.06,0.02,0.02,0.24,0.05,0.01,0.13];const snap = await db.collection("vectorProducts") .where("tenantId", "==", "tenant-a") .where("category", "==", "cameras") .findNearest("embeddingV1", FieldValue.vector(q), { limit: 5, distanceMeasure: "EUCLIDEAN", distanceResultField: "vectorDistance" }) .get();for (const doc of snap.docs) { console.log(doc.id, doc.get("vectorDistance"));}
8. Wrong approach: silently change the field dimension in place
Suppose embeddingV1 moves from 8 dimensions to 768
but the index and older documents remain 8-D. That is not a
gradual schema evolution; it is a broken vector contract. The
repair is a new versioned field/index, a backfill with explicit
progress state, dual-read evaluation, then a controlled cutover.
9. Index ownership and cleanup
Record an owner, purpose, model version, dimension, scalar prefilters, creation command, rollout date and removal gate for every vector index. Deleting an index too early can break live search; keeping obsolete indexes forever increases storage/write overhead and complicates migrations.
{ "owner": "atlasmart-search", "collectionGroup": "vectorProducts", "vectorField": "embeddingV1", "dimension": 8, "indexType": "flat", "prefilters": ["tenantId ASC", "category ASC"], "embeddingModel": "atlasmart-local-v1", "embeddingVersion": 1, "retireAfter": "v2 cutover + rollback window + zero v1 query traffic"}
10. Edition/mode/client matrix
| Surface | Vector capability | Important boundary |
|---|---|---|
| Standard Native Core | Managed nearest-neighbor search through supported server libraries; flat vector indexes; metadata prefilters | Maximum 2,048 dimensions; maximum 1,000 returned documents; no realtime snapshot listeners for vector search; current documented client-library support is Python, Node.js, Go, Java |
| Enterprise Native Core | Native Core semantics in Enterprise context | Enterprise indexing/billing differ from Standard; do not copy Standard billing equations blindly |
| Enterprise Native Pipeline |
findNearest transformation stage with broader
Pipeline client surface
|
Pipeline API and supported distance options are distinct; verify current stage and SDK behavior rather than treating it as Standard Core |
| MongoDB compatibility | Separate MongoDB-compatible query/index surface |
Do not assume Native findNearest,
vector-index commands, Rules, or pricing semantics map
one-for-one
|
| Emulator | Useful for fixture/security/application plumbing; recent emulator versions can store vector values | Composite/vector-index enforcement, production latency, billing, index build state, and all service limits are not production evidence |
Verification checklist
-
The optional gcloud command declares dimension 8 and
flat. - The query vector is validated before a managed call.
- The scalar prefilter fields are part of the composite vector index.
- Index creation and index readiness are treated as different states.
- Standard’s 1,000-result and supported-library statements are not copied to Enterprise Pipeline without checking its docs.
Production judgment and bridge to Lesson 3
An index makes KNN executable; it does not make the ranking useful. Lesson 3 turns to distance measures, thresholds, metadata prefilters and ranking interpretation, using the same six-product fixture so index mechanics and retrieval quality remain separate variables.
Knowledge check
- What vector index type does current Standard Native documentation require?
- Why does AtlasMart include tenantId/category in a composite vector index?
- Does emulator success prove a production composite/vector index exists?
- What is the current Standard Core maximum returned-document count for a nearest-neighbor query?
- What is safer than overwriting an 8-D field with a 768-D model?
Review the answers
1. Flat.
2. They are prefilters required by the retrieval/security contract before nearest-neighbor ranking.
3. No. The emulator does not enforce production composite-index requirements.
4. 1,000 documents.
5. Create a versioned field/index, backfill, evaluate, cut over, then retire the old version.
Summary and next step
This lesson established the working contract for Create/Manage Firestore Vector Indexes and Understand Supported Dimensions/Query Limits. Keep its edition/mode assumptions, trust boundary, verification evidence, and operational constraints explicit when reusing the pattern.
Next, continue to K-Nearest-Neighbor Queries, Distance Thresholds, Metadata Filters, and Result Ranking.
Authoritative references
- Firebase · Search with vector embeddings
- Google Cloud · Firestore Standard pricing
- Firebase · Connect to the Firestore emulator and understand differences from production
- Google Cloud · Enterprise Native Pipeline findNearest stage
- Firebase · Enterprise Native supported data types
- Google Cloud · Vertex AI embedding sample