146: Advanced MongoDB Features — Change Streams, Time Series, GridFS, Geospatial, Search, Vector Search, and Specialized Workloads
Learning objectives
You will learn to:
- choose specialized MongoDB features based on workload;
- design reliable change-stream consumers;
- understand time-series collections;
- understand GridFS and when not to use it;
- model geospatial data and queries;
- distinguish classic text indexes from MongoDB Search;
- understand MongoDB Vector Search;
- understand hybrid search at a practical level;
- understand specialized feature limitations;
- avoid forcing every data problem into one MongoDB feature.
Why specialized features come late
You first learned:
documents modeling CRUD indexes aggregation transactions replication sharding security operations driver
Now you can evaluate specialized features without treating them as magic.
Change streams recap
Change streams let an application subscribe to MongoDB changes on:
- collection;
- database;
- deployment.
They are available on replica sets and sharded clusters.
Example:
const stream = db
.collection('orders')
.watch([
{
$match: {
operationType: {
$in: [
'insert',
'update',
],
},
},
},
]);
Consume:
for await (const change of stream) {
await handleChange(change);
}
Change event shape
Can include fields such as:
_id resume token operationType clusterTime ns documentKey updateDescription fullDocument fullDocumentBeforeChange
depending operation/options/configuration.
Do not assume full document always present.
Full document lookup
For updates, request post-change document with supported option such as:
fullDocument: "updateLookup"
This performs lookup and can add load.
If you only need changed field names, use updateDescription.
Pre/post images
MongoDB can store pre/post images for configured collections.
Useful for:
- audit;
- diff;
- event processors requiring old/new.
Costs:
- storage;
- privileges;
- retention;
- operational complexity.
Do not enable globally without need.
Resume
Store resume token after successfully applying event:
receive ↓ process idempotently ↓ persist output/state ↓ persist resume token
If you persist token before completing side effect, crash can skip unfinished event.
If you persist token after non-idempotent side effect, crash can repeat side effect.
Therefore consumers should be idempotent.
Change stream and exactly-once myth
A change stream alone does not automatically produce exactly-once external side effects.
For:
send email charge card publish webhook
use:
- idempotency keys;
- durable processed-event record;
- outbox;
- transactional projection design.
Rebuildable projection
A robust read model consumer should ideally support:
rebuild from source + resume live changes
If resume history expires, you can rebuild.
Do not make one forgotten resume token the only way to reconstruct critical data.
Time-series data
Workloads:
- sensors;
- metrics;
- IoT;
- telemetry;
- measurements.
Time-series collection groups data by:
time field meta field granularity/bucketing
Example:
db.createCollection(
"deviceMetrics",
{
timeseries: {
timeField: "timestamp",
metaField: "device",
granularity: "seconds"
}
}
)
Document:
{
timestamp: new Date(),
device: {
tenantId,
deviceId,
region: "south"
},
temperature: 28.4,
humidity: 63
}
Time-series meta field
Put stable metadata used to group/filter:
device ID sensor type tenant site
Avoid frequently changing high-cardinality metadata structure that defeats efficient bucketing.
Design from query patterns.
Time-series limitations
Time-series collections have specific limitations.
As of current MongoDB documentation:
- change streams are not supported on time-series collections;
- MongoDB Search/Vector Search is not supported for time-series collections in the ordinary way;
- some schema/collection operations have restrictions.
Check current version before choosing.
Do not assume a normal collection feature automatically works on time series.
Time-series retention
Use expireAfterSeconds for automatic data expiration where appropriate.
TTL cleanup is asynchronous.
For regulatory/analytics retention, design archival before expiry.
Downsampling
High-frequency telemetry can be expensive long-term.
Architecture:
raw 1-second metrics retained 7 days 5-minute aggregates retained 1 year
Use aggregation/materialized summaries/Atlas features according to needs.
GridFS
MongoDB GridFS stores large files by splitting them into chunks plus metadata.
Collections conceptually:
fs.files fs.chunks
Use when:
- files need MongoDB-managed storage semantics;
- files exceed document size;
- operational architecture favors DB-backed file storage.
When object storage is better
For:
- photos;
- videos;
- PDFs;
- public assets;
- large downloads;
S3-compatible/object storage + CDN is often better:
- cheaper;
- scalable;
- range requests/CDN;
- lifecycle policies;
- specialized durability.
GridFS is not automatically the right choice because app already uses MongoDB.
GridFS Node driver
Driver exposes GridFSBucket.
Concept:
const bucket = new GridFSBucket(db);
await pipeline(
fileInput,
bucket.openUploadStream(
safeFilename,
{
metadata: {
tenantId,
},
},
),
);
Download:
await pipeline(
bucket.openDownloadStream(fileId),
httpResponse,
);
Use streaming/backpressure.
GridFS security
Do not trust original filename for authorization.
Metadata:
tenantId ownerId contentType size hash/scanning status
Application query should scope file ID + tenant.
Uploaded file policy remains:
- size limit;
- MIME/signature;
- malware;
- content-disposition;
- safe serving.
Geospatial model
GeoJSON Point:
{
location: {
type: "Point",
coordinates: [
78.1198,
9.9252
]
}
}
Coordinates are:
longitude latitude
Index:
db.places.createIndex({
location: "2dsphere"
})
$near
Find nearest places:
db.places.find({
location: {
$near: {
$geometry: {
type: "Point",
coordinates: [
78.12,
9.92
]
},
$maxDistance: 5000
}
}
})
Use index.
Distance units depend on operator.
Check docs.
$geoWithin
Find points inside polygon/shape.
Useful for:
- service area;
- delivery zone;
- geofencing.
Geospatial boundary precision and coordinate reference assumptions matter.
Do not implement legal/cadastral precision blindly with general GeoJSON.
$geoNear
Aggregation stage can calculate distance and enrich output.
Must follow stage/index rules.
Useful:
nearest stores then lookup inventory then filter availability
But query may become expensive.
Classic text search
Classic MongoDB text index supports basic search.
db.articles.createIndex({
title: "text",
body: "text"
})
Query:
{
$text: {
$search: "mongodb indexing"
}
}
Useful for simple workloads.
Limited compared with MongoDB Search.
MongoDB Search
MongoDB Search provides Lucene-based search capabilities in supported deployments/products.
Capabilities include:
- relevance;
- analyzers;
- autocomplete;
- fuzzy matching;
- facets;
- compound search;
- highlighting.
Search indexes are managed separately from normal MongoDB indexes.
Pipeline uses:
$search $searchMeta
Do not use createIndex() and expect Atlas Search behavior.
Search index mapping
Define fields/analyzers deliberately.
Dynamic mapping is easy for prototypes but can index more fields than needed.
Production:
- explicit searchable fields;
- analyzers/language;
- stored source choices;
- autocomplete;
- synonyms where appropriate.
Search indexing consumes storage/resources.
Autocomplete
A prefix-like UX should not use:
{
name: {
$regex: userInput,
}
}
over millions of documents.
Search autocomplete index/operator can provide better scalable relevance behavior.
Search security
Search results must still enforce tenant/access scope.
Include tenant filter in search pipeline using supported compound filters or architecture.
Do not search global index then filter unauthorized results only after returning too many.
Authorization belongs before/exactly within data query.
Vector search
Vector search finds semantically similar vectors.
Typical flow:
text/image/document ↓ embedding model ↓ vector array ↓ vector index ↓ nearest-neighbor query
Document:
{
tenantId,
content: "...",
embedding: [
0.013,
-0.22,
...
]
}
Vector index
MongoDB's vector search uses a specialized vector index in supported deployment.
Query uses $vectorSearch stage.
Concept:
{
$vectorSearch: {
index: "content_vector",
path: "embedding",
queryVector: [...],
numCandidates: 200,
limit: 10,
filter: {
tenantId: tenantId
}
}
}
Exact supported filters/options depend on current MongoDB version/service.
Do not copy dimensions/index settings from another embedding model.
Embedding dimensions
Vector size must match index/model.
If model changes:
1536 dimensions → 3072 dimensions
existing index/data may require migration/new field/index.
Version embeddings:
{
embeddingModel: "model-x-v2",
embedding: [...]
}
Similarity function
Vector indexes support similarity metrics such as cosine/dot/euclidean depending service/config.
Match embedding model recommendation.
Do not choose metric by intuition.
Hybrid search
Combine:
lexical relevance + semantic/vector relevance
Useful when exact terms matter and semantic similarity helps.
Example:
"Node 26 memory leak"
Lexical exact version term plus semantic meaning.
Hybrid ranking architecture may use reciprocal-rank fusion or product-specific scoring.
Use MongoDB's current Search/Vector capabilities rather than manually merging huge result sets when platform provides suitable feature.
Retrieval-Augmented Generation (RAG)
Vector search can retrieve context for LLM.
Security rules:
- filter tenant/permissions during retrieval;
- never rely on model to hide unauthorized text;
- treat retrieved documents as untrusted content;
- apply prompt-injection defenses;
- log carefully;
- include source references where product requires.
Database authorization comes before generation.
Vector data cost
Embeddings consume storage and indexing memory.
Millions of high-dimensional vectors can be significant.
Measure:
- index size;
- query latency;
- ingestion rate;
- model embedding cost;
- reindex cost.
Do not add vector field to every document without product need.
Search consistency
Search indexes may have synchronization delay relative to database writes.
Do not use Search index for a strongly consistent authorization or financial existence check.
Use ordinary Mongo query for authoritative state.
Search is retrieval system.
Search pagination
Search supports specialized pagination mechanisms.
Do not use deep $skip through relevance results.
Use search-after/search-before style APIs where supported.
Specialized workload decision table
| Need | Feature |
|---|---|
| realtime DB changes | Change Streams |
| sensor telemetry | Time Series |
| DB-managed large binary | GridFS |
| nearest location | 2dsphere |
| full-text/autocomplete | MongoDB Search |
| semantic similarity | Vector Search |
| strict transactional truth | ordinary collection + transactions/atomic writes |
Do not solve every problem with aggregation.
Failure clinic
Time-series + change stream assumed supported
Wrong feature combination.
GridFS for public images without considering object storage/CDN
Cost/performance mismatch.
geo coordinates reversed
Wrong locations.
regex used as search engine
Slow/poor relevance.
vector query lacks tenant filter
Security breach.
search result treated as authoritative latest state
Index lag problem.
embedding model changed without migration version
Index incompatibility.
change-stream token stored before side effect
Potential lost event.
Exercises
- Build change-stream projection with idempotency.
- Persist resume token after durable processing.
- Create time-series collection for device readings.
- Design raw/downsampled retention.
- Stream a file into GridFS and compare with object-storage design.
- Build 2dsphere nearest-place query.
- Design MongoDB Search index for product name/description/autocomplete.
- Design vector document with tenant filter.
- Plan embedding-model migration.
- Threat-model a RAG search endpoint.
- Explain which specialized features cannot be combined on time-series collections.
Mastery checklist
Explain:
- change stream resume/idempotency;
- time-series model/limits;
- GridFS/object storage trade-off;
- geospatial indexes;
- classic text versus Search;
- Search indexes;
- Vector Search;
- hybrid/RAG security;
- search consistency;
- specialized feature selection.
Official references
- https://www.mongodb.com/docs/manual/changeStreams/
- https://www.mongodb.com/docs/manual/core/timeseries-collections/
- https://www.mongodb.com/docs/manual/core/gridfs/
- https://www.mongodb.com/docs/manual/geospatial-queries/
- https://www.mongodb.com/docs/search/
- https://www.mongodb.com/docs/atlas/atlas-vector-search/
- https://roadmap.sh/mongodb
Additional specialized-feature depth: lifecycle and architecture boundaries
Specialized indexes and streaming features introduce their own lifecycle.
Search/vector index lifecycle
You need:
create index initial build monitor sync deploy query change mapping/model rebuild new index switch traffic remove old
Do not edit a production index/model and hope every query remains compatible.
For major search changes, version index name:
products_search_v1 products_search_v2
Build v2, validate, then switch.
Embedding lifecycle
Vector data is derived.
Store enough metadata to reproduce:
{
embedding: [...],
embeddingModel:
"model-2026-08",
embeddedAt:
new Date(),
sourceHash:
"sha256..."
}
When source changes, embedding becomes stale.
Background worker detects/recomputes.
Do not recalculate embedding synchronously on every read.
Vector filtering before retrieval
Permission filter must be supported by vector index/filter fields.
If user only allowed project P1:
filter projectId=P1 inside vector search
not:
retrieve top 10 global remove unauthorized
Otherwise:
- may return zero useful results;
- can leak timing/metadata;
- violates least exposure.
Change-stream scaling
One change stream per request/client is expensive.
Instead:
one/few backend consumers → internal pubsub → WebSocket/SSE clients
for many users.
At multi-instance scale, pubsub may need Redis/NATS/Kafka/etc.
Do not open 100k Mongo change streams because 100k browser clients connected.
Change-stream partition/order
Ordering is defined by change stream/topology semantics, but consumers should not invent total business order across unrelated entities if not required.
For per-aggregate workflow, use:
version sequence event timestamp
and idempotency.
GridFS range downloads
Large media clients may request byte ranges.
GridFS stream APIs are not automatically CDN-grade media serving.
Object storage/CDN handles:
- range;
- caching;
- edge;
- signed URLs better for many media workloads.
Time-series meta cardinality
If meta field unique for every measurement:
meta:
{
requestId:
randomUUID()
}
bucketing cannot group effectively.
Meta should represent stable series identity.
Geospatial + tenant
Compound geospatial index patterns have restrictions/order considerations.
For multi-tenant places, design query/index according to current Mongo geospatial compound-index rules.
Do not omit tenant security just because $near query syntax is specialized.
Search index lag UX
After product updated:
normal Mongo detail shows new title search may show old title briefly
UI may:
- accept eventual search;
- invalidate/local update;
- show authoritative detail on click.
Document consistency.
Additional exercises
- Version a Search index and plan zero-downtime switch.
- Design embedding refresh worker using source hash.
- Ensure vector filter contains tenant/project.
- Replace one-change-stream-per-client with backend fanout architecture.
- Compare GridFS versus object storage for video.
- Fix high-cardinality time-series meta design.
- Design UX for search-index lag.
Production mastery check
Specialized Mongo features should be treated as subsystems with indexing, consistency, scaling, and recovery behavior, not one-line query operators.
