[GH-ISSUE #8867] MySQL inserted id #19849

Open
opened 2026-04-15 19:12:05 -05:00 by GiteaMirror · 1 comment
Owner

Originally created by @howlettt on GitHub (Mar 31, 2026).
Original GitHub issue: https://github.com/better-auth/better-auth/issues/8867

Originally assigned to: @ping-maxwell on GitHub.

Noticed the following code that relies on finding the inserted row based on the largest id, which could fail in a high load scenario when another new row is inserted before the select finishes. I believe the inserted id is returned when using MySQL via the insertId member on the response, so this could be improved.

https://github.com/better-auth/better-auth/blob/85e37693a2766c7560c50d7ab675adfba8c681a2/packages/kysely-adapter/src/kysely-adapter.ts#L113-L144

Originally created by @howlettt on GitHub (Mar 31, 2026). Original GitHub issue: https://github.com/better-auth/better-auth/issues/8867 Originally assigned to: @ping-maxwell on GitHub. Noticed the following code that relies on finding the inserted row based on the largest id, which could fail in a high load scenario when another new row is inserted before the select finishes. I believe the inserted id is returned when using MySQL via the `insertId` member on the response, so this could be improved. https://github.com/better-auth/better-auth/blob/85e37693a2766c7560c50d7ab675adfba8c681a2/packages/kysely-adapter/src/kysely-adapter.ts#L113-L144
GiteaMirror added the databasebug labels 2026-04-15 19:12:05 -05:00
Author
Owner

@dosubot[bot] commented on GitHub (Mar 31, 2026):

Hi @howlettt! I'm Dosu and I’m helping the better-auth team.

Good catch — you're right that this is a real race condition, and you're also right that Kysely already exposes insertId on its QueryResult interface (as a bigint) for MySQL auto-increment inserts [1]. The current code simply discards the result of await builder.execute() instead of capturing it [2].

A fix for the auto-increment case could be as straightforward as:

const result = await builder.execute();
const insertId = result[0]?.insertId;
if (insertId) {
  res = await db
    .selectFrom(model)
    .selectAll()
    .where(getFieldName({ model, field: "id" }), "=", Number(insertId))
    .executeTakeFirst();
  return res;
}

For context, PR #6634 previously proposed a fix for this (including LAST_INSERT_ID() usage and race condition tests), but it was closed without merging. The current recommended workaround is to provide a custom generateId function so the ID is known before the insert, making the follow-up SELECT reliable [3].

Worth noting this insertId approach only helps with auto-increment integer PKs — UUID/CUID keys generated at the DB level would still need a different strategy.

To reply, just mention @dosu.


How did I do? Good | Irrelevant | Incorrect | Verbose | Hallucination | Report 🐛 | Other

Chat with Dosu Open in Cursor Join Discord Share on X

<!-- gh-comment-id:4166210384 --> @dosubot[bot] commented on GitHub (Mar 31, 2026): <!-- Greeting --> Hi @howlettt! I'm [Dosu](https://go.dosu.dev/dosubot) and I’m helping the better-auth team. <!-- Answer --> Good catch — you're right that this is a real race condition, and you're also right that Kysely already exposes `insertId` on its `QueryResult` interface (as a `bigint`) for MySQL auto-increment inserts [[1]](https://raw.githubusercontent.com/kysely-org/kysely/master/src/driver/database-connection.ts). The current code simply discards the result of `await builder.execute()` instead of capturing it [[2]](https://github.com/better-auth/better-auth/blob/df7f8dda9f884a486f05d6cc91dfe53b8f34e7a9/packages/kysely-adapter/src/kysely-adapter.ts#L113-L114). A fix for the auto-increment case could be as straightforward as: ```typescript const result = await builder.execute(); const insertId = result[0]?.insertId; if (insertId) { res = await db .selectFrom(model) .selectAll() .where(getFieldName({ model, field: "id" }), "=", Number(insertId)) .executeTakeFirst(); return res; } ``` For context, [PR #6634](https://github.com/better-auth/better-auth/pull/6634) previously proposed a fix for this (including `LAST_INSERT_ID()` usage and race condition tests), but it was closed without merging. The current recommended workaround is to provide a custom `generateId` function so the ID is known *before* the insert, making the follow-up SELECT reliable [[3]](https://github.com/better-auth/better-auth/issues/1480#issuecomment-2744359832). Worth noting this `insertId` approach only helps with auto-increment integer PKs — UUID/CUID keys generated at the DB level would still need a different strategy. <!-- Dosu Comment Footer --> *To reply, just mention [@dosu](https://go.dosu.dev/dosubot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=brand-link).* --- <sup>How did I do? [Good](https://app.dosu.dev/response-feedback/eb9e740b-534a-4a2b-8c96-b7364f503fe3?feedback_type=great_response&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-great_response) | [Irrelevant](https://app.dosu.dev/response-feedback/eb9e740b-534a-4a2b-8c96-b7364f503fe3?feedback_type=irrelevant_answer&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-irrelevant_answer) | [Incorrect](https://app.dosu.dev/response-feedback/eb9e740b-534a-4a2b-8c96-b7364f503fe3?feedback_type=incorrect_sources&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-incorrect_sources) | [Verbose](https://app.dosu.dev/response-feedback/eb9e740b-534a-4a2b-8c96-b7364f503fe3?feedback_type=too_verbose&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-too_verbose) | [Hallucination](https://app.dosu.dev/response-feedback/eb9e740b-534a-4a2b-8c96-b7364f503fe3?feedback_type=hallucination&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-hallucination) | [Report 🐛](https://app.dosu.dev/response-feedback/eb9e740b-534a-4a2b-8c96-b7364f503fe3?feedback_type=bug_report&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-bug_report) | [Other](https://app.dosu.dev/response-feedback/eb9e740b-534a-4a2b-8c96-b7364f503fe3?feedback_type=other&utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=feedback-other)</sup> [![Chat with Dosu](https://dosu.dev/dosu-chat-badge.svg)](https://app.dosu.dev/cdda13d9-dd27-4d31-b09a-5d8bec92de21/ask?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=chat-badge)&nbsp;[![Open in Cursor](https://dosu.dev/dosu-in-cursor.svg)](https://cursor.com/link/prompt?text=Good%20catch%20%E2%80%94%20you%27re%20right%20that%20this%20is%20a%20real%20race%20condition%2C%20and%20you%27re%20also%20right%20that%20Kysely%20already%20exposes%20%60insertId%60%20on%20its%20%60QueryResult%60%20interface%20%28as%20a%20%60bigint%60%29%20for%20MySQL%20auto-increment%20inserts%20%5B%5B1%5D%5D%28https%3A//raw.githubusercontent.com/kysely-org/kysely/master/src/driver/database-connection.ts%29.%20The%20current%20code%20simply%20discards%20the%20result%20of%20%60await%20builder.execute%28%29%60%20instead%20of%20capturing%20it%20%5B%5B2%5D%5D%28https%3A//github.com/better-auth/better-auth/blob/df7f8dda9f884a486f05d6cc91dfe53b8f34e7a9/packages/kysely-adapter/src/kysely-adapter.ts%23L113-L114%29.%0A%0AA%20fix%20for%20the%20auto-increment%20case%20could%20be%20as%20straightforward%20as%3A%0A%0A%60%60%60typescript%0Aconst%20result%20%3D%20await%20builder.execute%28%29%3B%0Aconst%20insertId%20%3D%20result%5B0%5D%3F.insertId%3B%0Aif%20%28insertId%29%20%7B%0A%20%20res%20%3D%20await%20db%0A%20%20%20%20.selectFrom%28model%29%0A%20%20%20%20.selectAll%28%29%0A%20%20%20%20.where%28getFieldName%28%7B%20model%2C%20field%3A%20%22id%22%20%7D%29%2C%20%22%3D%22%2C%20Number%28insertId%29%29%0A%20%20%20%20.executeTakeFirst%28%29%3B%0A%20%20return%20res%3B%0A%7D%0A%60%60%60%0A%0AFor%20context%2C%20%5BPR%20%236634%5D%28https%3A//github.com/better-auth/better-auth/pull/6634%29%20previously%20proposed%20a%20fix%20for%20this%20%28including%20%60LAST_INSERT_ID%28%29%60%20usage%20and%20race%20condition%20tests%29%2C%20but%20it%20was%20closed%20without%20merging.%20The%20current%20recommended%20workaround%20is%20to%20provide%20a%20custom%20%60generateId%60%20function%20so%20the%20ID%20is%20known%20%2Abefore%2A%20the%20insert%2C%20making%20the%20follow-up%20SELECT%20reliable%20%5B%5B3%5D%5D%28https%3A//github.com/better-auth/better-auth/issues/1480%23issuecomment-2744359832%29.%0A%0AWorth%20noting%20this%20%60insertId%60%20approach%20only%20helps%20with%20auto-increment%20integer%20PKs%20%E2%80%94%20UUID/CUID%20keys%20generated%20at%20the%20DB%20level%20would%20still%20need%20a%20different%20strategy.)&nbsp;[![Join Discord](https://img.shields.io/badge/join-5865F2?logo=discord&logoColor=white&label=)](https://go.dosu.dev/discord-bot?utm_source=github&utm_medium=bot-comment&utm_campaign=github-assistant&utm_content=join-discord)&nbsp;[![Share on X](https://img.shields.io/badge/X-share-black)](https://twitter.com/intent/tweet?text=%40dosu_ai%20helped%20me%20solve%20this%20issue!&url=https%3A//github.com/better-auth/better-auth/issues/8867)
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: github-starred/better-auth#19849