Index suggestion for collection size is gated on autoIndex, so it only fires where it is redundant
Nobody has claimed this yet.
Assessment
- Difficulty
- 2/5
- Estimated time
- 1-3 hours
- Newbie friendliness
- 76/100
- Issue type
- Bug
- Clarity
- Clearly specified
- Activity status
- Quiet
- Tech stack
- typescript
- Domain
- database
Research direction
Read ensureIndexForField in src/indexes/auto-index.ts, focusing on the shouldAutoIndex guard and its sole call to checkCollectionSizeForIndex. Run the TypeScript reproduction from the issue with and without autoIndex, then verify that collection-size advice appears only when manual indexing leaves a matching index absent and stays quiet for eager indexing.
Written by the indexing model from the issue text.
Description
Summary
The collection-size index suggestion is gated on the wrong side of shouldAutoIndex. It is only reachable when autoIndex: 'eager' is set — where it is redundant, because the very next statement creates the index it asks for — and is unreachable when indexing is manual, which is the only situation where the advice has a recipient.
So the suggestion fires exactly where it is useless, and is silent exactly where it would be useful.
Details
ensureIndexForField in src/indexes/auto-index.ts (v0.6.17):
if (hasVirtualPropPath(fieldPath)) return
if (!shouldAutoIndex(collection)) return // (1) eager-only from here on
const existingIndex = Array.from(collection.indexes.values()).find(...)
if (existingIndex) return // (2) index is genuinely absent
if (isDevModeEnabled()) {
checkCollectionSizeForIndex( // (3) "you may want an index on x"
collection.id || `unknown`,
collection.size,
fieldPath,
)
}
try {
collection.createIndex(...) // (4) ...creates that index
checkCollectionSizeForIndex has exactly one call site — this one. Consequences:
- With
autoIndex: 'eager': every field path first queried on a collection pastcollectionSizeThresholdlogsCollection has N items. Queries on "url" may benefit from an index. / Add index: collection.createIndex((row) => row.url)— immediately before the library creates that index itself. It recurs after every gc cycle, becauseCollectionLifecycleManager.performCleanupempties the index map and the next compiled query rebuilds through the same path. Following the printed advice "fixes" it only by racing ahead of the check. - Without
autoIndex: nocollection-sizesuggestion is ever emitted, for any collection at any size. A manually-indexed collection missing an index on a hot field gets no size-based advice at all.slow-querystill fires, but only once an average exceedsslowQueryThresholdMs(10ms), so it is reactive rather than predictive, and the join path'sJoin requires an indexcovers joins only — a plainwhere(eq(row.url, …))full scan gets nothing before the fact.
Reproduction
import {
createCollection,
createLiveQueryCollection,
eq,
localOnlyCollectionOptions,
BasicIndex,
} from '@tanstack/db'
const collection = createCollection({
...localOnlyCollectionOptions({ id: 'probe', getKey: (r: { id: string; url: string }) => r.id }),
autoIndex: 'eager',
defaultIndexType: BasicIndex,
})
collection.insert(
Array.from({ length: 1100 }, (_, i) => ({ id: `n${i}`, url: `https://example.test/${i}` })),
)
const q = createLiveQueryCollection((qb) =>
qb.from({ row: collection }).where(({ row }) => eq(row.url, 'https://example.test/7')),
)
await q.preload()
// console: Collection has 1100 items. Queries on "url" may benefit from an index. …
// collection.indexes → 1 (the index the warning asked for, created by the library)
Dropping autoIndex/defaultIndexType from the same script silences the suggestion entirely, while the collection now genuinely has no index — the inverse of the intended behaviour.
Suggested fix
Invert the guard rather than reorder the emit: run the size check when shouldAutoIndex(collection) is false (and no matching index exists), so it advises the users who must act on it, and stays quiet for collections the library is about to index itself. That is smaller than moving the emit below createIndex, and it restores the diagnostic instead of just quieting it.
Workaround
For anyone hitting the noise today, the public configureIndexDevMode seam works — drop collection-size and forward the rest, which leaves slow-query and the join full-scan warning intact:
configureIndexDevMode({
onSuggestion: (suggestion) => {
if (suggestion.type === 'collection-size') return
console.warn(`[TanStack DB] [${suggestion.collectionId}] ${suggestion.message}`)
},
})
Environment
@tanstack/db 0.6.17 (also present in 0.6.14), @tanstack/react-db 0.1.95, Node 22, verified against the published source in node_modules.
Aside: the index itself works well
Not part of the report, but useful context for anyone finding this issue while deciding whether to enable eager indexing. Same 22,830-row collection, indexed vs unindexed:
| eager | no autoIndex | |
|---|---|---|
where eq(url), 20 runs |
5ms / 2ms | 229ms / 201ms |
leftJoin on id, 5 runs |
62ms | 217ms |
The suggestion is noise; the auto-indexing it accompanies is doing real work.
- Dominant language
- TypeScript
- Stars
- 3.9k
- Forks
- 266
- Avg merge
- 1d 4h
- Merged PRs (30d)
- 52
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
More from TanStack/db
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 76/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 68/100
Similar issues
-
calcite-components needs triage refactor
Difficulty 2/5 1-3 hours Newbie friendliness 75/100
Esri/calcite-design-system#15203 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 91/100
-
community first-timers-only good first issue hacktoberfest help wanted low hanging fruit up-for-grabs
Difficulty 1/5 Under an hour Newbie friendliness 95/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100
Automattic/studio#4908 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100