Skip to content

fix: add compound [token, expiresAt] index on session table#314

Open
elpiarthera wants to merge 2 commits into
get-convex:mainfrom
elpiarthera:fix/issue-305-session-token-expiresAt-index
Open

fix: add compound [token, expiresAt] index on session table#314
elpiarthera wants to merge 2 commits into
get-convex:mainfrom
elpiarthera:fix/issue-305-session-token-expiresAt-index

Conversation

@elpiarthera
Copy link
Copy Markdown

@elpiarthera elpiarthera commented Apr 6, 2026

Summary

  • Added compound ["token", "expiresAt"] index to session table in both the schema generator (create-schema.ts) and the auto-generated component schema
  • Fixes "Querying without an index" warning when using multi-session plugin, which queries by token eq + expiresAt range
  • Without this compound index, the query falls back to a full table scan

Test plan

  • npm run build passes
  • npm run lint passes (0 errors)
  • npm test passes (34/34)
  • Verified index naming follows existing convention (token_expiresAt)

Fixes #305

Orchestrator: Zeta — VantageOS Team Dev | 2026-04-06

Summary by CodeRabbit

  • Chores
    • Added a composite index for sessions to improve session token lookup and expiration handling performance. This results in faster authentication and session-validation operations, reduced latency during token checks, and more efficient expiration processing. The schema generation was also made more robust to prevent unintended mutations during index name computation.

When using the multi-session plugin, queries on the session table filter
by token eq + expiresAt range. Without a compound index, this falls back
to a full table scan, triggering a "Querying without an index" warning.

Fixes get-convex#305
@vercel
Copy link
Copy Markdown

vercel Bot commented Apr 6, 2026

Someone is attempting to deploy a commit to the Convex Team on Vercel.

A member of the Team first needs to authorize it.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 6, 2026

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 6267760e-eaa6-4ec3-bd9c-281ec575e28f

📥 Commits

Reviewing files that changed from the base of the PR and between 0184147 and a881995.

📒 Files selected for processing (1)
  • src/client/create-schema.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/client/create-schema.ts

📝 Walkthrough

Walkthrough

Added a composite index ["token","expiresAt"] to the session model: index declared in client schema generation and emitted in the runtime schema to address Convex query warnings.

Changes

Cohort / File(s) Summary
Schema index configuration
src/client/create-schema.ts
Extended indexFields.session to include the new composite index ["token","expiresAt"] and adjusted index-name generation to avoid mutating input arrays when sorting.
Session table schema
src/component/schema.ts
Added .index("token_expiresAt", ["token","expiresAt"]) to the session table definition. No other table fields were changed.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

  • fix: match composite index fields without underscore prefix #297 — Adds the composite session index and tweaks index-name sorting logic (strongly related to composite-index handling).
  • get-convex/better-auth#... (if applicable) — Follow-up PR addressing index-name generation consistency across array vs non-array indexes.

Poem

🐇🌿 I nibble code and map the way,
A token trail for queries' sway.
Two fields aligned, expires and key,
Now searches hop more swift and free.
Hooray — the sessions run with glee!

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: adding a compound [token, expiresAt] index to the session table, which is the primary objective of this PR.
Linked Issues check ✅ Passed The PR successfully addresses issue #305 by adding the compound [token, expiresAt] index to resolve the Convex 'Querying without an index' warning for session queries with the multi-session plugin.
Out of Scope Changes check ✅ Passed All changes are within scope. The PR includes the compound index addition and a technical fix to preserve field order in the schema generator, both directly related to resolving the index issue.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
src/client/create-schema.ts (1)

128-135: ⚠️ Potential issue | 🔴 Critical

The .sort() breaks compound index field ordering.

The alphabetical sort ensures consistent naming but breaks Convex's field-order requirement. For ["token", "expiresAt"], this produces ["expiresAt", "token"] - the opposite of what the query needs.

Consider preserving the original field order and deriving the index name from it:

🛠️ Proposed fix to preserve field order
     const indexes =
       mergedIndexFields(tables)[
         tableKey as keyof typeof mergedIndexFields
       ]?.map((index) => {
-        const indexArray = Array.isArray(index) ? index.sort() : [index];
-        const indexName = indexArray.join("_");
+        const indexArray = Array.isArray(index) ? index : [index];
+        const indexName = [...indexArray].sort().join("_");
         return `.index("${indexName}", ${JSON.stringify(indexArray)})`;
       }) || [];

This preserves the field order for the index definition while still sorting only for the name (for consistency). Alternatively, keep field order in the name as well since it's more descriptive of the query pattern.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/client/create-schema.ts` around lines 128 - 135, The current logic in
create-schema.ts uses Array.prototype.sort() on index arrays (see
mergedIndexFields, tableKey) which reorders fields and breaks Convex's required
field ordering; change the code so you do NOT sort the actual index array used
for the index definition (preserve original order for index creation) but still
derive a stable index name by creating a separate sorted copy just for naming
(e.g., keep the original indexArray as-is for the .index(...) argument and
compute indexName from a sorted shallow copy), ensuring indexName remains
deterministic while the index field order stays intact.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Outside diff comments:
In `@src/client/create-schema.ts`:
- Around line 128-135: The current logic in create-schema.ts uses
Array.prototype.sort() on index arrays (see mergedIndexFields, tableKey) which
reorders fields and breaks Convex's required field ordering; change the code so
you do NOT sort the actual index array used for the index definition (preserve
original order for index creation) but still derive a stable index name by
creating a separate sorted copy just for naming (e.g., keep the original
indexArray as-is for the .index(...) argument and compute indexName from a
sorted shallow copy), ensuring indexName remains deterministic while the index
field order stays intact.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 0a477309-44cd-411a-b535-e5bd0cafbcd1

📥 Commits

Reviewing files that changed from the base of the PR and between c790754 and 0184147.

📒 Files selected for processing (2)
  • src/client/create-schema.ts
  • src/component/schema.ts

The .sort() on index arrays was reordering compound index fields
alphabetically, breaking order-dependent queries. Sort only the
copy used for the index name, keep original order for the definition.
@erquhart
Copy link
Copy Markdown
Member

erquhart commented Apr 23, 2026

Thanks for this - coderabbit's callout is legit and points to a bigger issue (and coderabbit's fix doesn't actually fix it). Not brought on by your pr but we've been getting away with it because all of our compound indexes so far happened to be in alphabetical order and the one you're adding isn't. Will look at this soon.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Missing compound [token, expiresAt] index on session table after upgrading to better-auth 1.5.5

2 participants