Around Go: MongoDB and Redis · 3 MIN READ

MongoDB: design the query and its compound index together

Use explain evidence, tenant predicates and stable pagination rather than adding indexes blindly.

A query that is fast with ten documents may scan a large collection after real traffic arrives. Shape the filter, sort and returned fields around an actual use case, then inspect the execution plan and the documents examined. Indexes improve selected reads while adding write, memory and maintenance cost.

Around Go: data stores · A MAP OF THE IDEA

  1. Filter and sort
  2. Candidate index
  3. Explain evidence
  4. Measured write cost

Useful when

  • Use explain evidence, tenant predicates and stable pagination rather than adding indexes blindly.

Watch out

  • The useful plan depends on filter, sort, selectivity and index shape. Explain measures examined work; a client pool setting does not guarantee index use.

Implementation & operation cost: Each index consumes storage, memory and write maintenance; keep it only when the measured access pattern earns that cost.

01

Create an index for one access pattern

In an isolated development database, consider a tenant’s newest notes. A compound index starts with tenant equality and then the chosen sort keys. Keep the tie-breaker consistent with pagination so equal timestamps do not create unstable page boundaries.

javascript
db.notes.createIndex({tenant: 1, createdAt: -1, _id: -1})
db.notes.find({tenant: "demo"}, {body: 1, createdAt: 1})
  .sort({createdAt: -1, _id: -1}).limit(20).explain("executionStats")
Read the code

These mongosh commands assume demo documents in a development database. Compare nReturned, totalKeysExamined and totalDocsExamined and inspect the winning plan; explain executionStats runs the query and can itself add load.

02

Use a stable continuation predicate

For descending pagination, continue before the last (createdAt, _id) pair instead of repeatedly skipping an ever-growing number of earlier results. Match the sort and predicate with the index, and define what happens when documents change between pages.

javascript
db.notes.find({tenant: "demo", $or: [
  {createdAt: {$lt: ISODate("2026-10-01T00:00:00Z")}},
  {createdAt: ISODate("2026-10-01T00:00:00Z"),
   _id: {$lt: ObjectId("650000000000000000000001")}}
]}).sort({createdAt: -1, _id: -1}).limit(20)
Read the code

The timestamp and ObjectId are example continuation values, not an offset. New writes may change a live listing; a stable ordering is not automatically a snapshot of the collection across multiple requests.

03

Verify selectivity and write cost

A large limit, broad regex, missing tenant condition or incompatible sort can overwhelm a previously adequate pool. Index order, multikey behavior and collation affect usable plans. Measure representative data distribution and write latency before retaining another index; hints can hide a modeling error.

TAKE THIS WITH YOU

Design filter, sort, projection and continuation together, verify examined work with explain, and account for index maintenance on every write.

Check your understanding

Why inspect explain after creating an index?

Go to the source

Progress stays in this browser. No account needed.