diff --git a/packages/payload/src/collections/operations/delete.ts b/packages/payload/src/collections/operations/delete.ts index a08e6c15f48..98adf67cedc 100644 --- a/packages/payload/src/collections/operations/delete.ts +++ b/packages/payload/src/collections/operations/delete.ts @@ -136,7 +136,7 @@ export const deleteOperation = async < const errors: BulkOperationResult['errors'] = [] - const promises = docs.map(async (doc) => { + const processDoc = async (doc: (typeof docs)[number]) => { let result const { id } = doc @@ -307,18 +307,17 @@ export const deleteOperation = async < }) } return null - }) + } - // Process sequentially when using single transaction mode to avoid shared state issues - // Process in parallel when using one transaction for better performance - let awaitedDocs - if (req.payload.db.bulkOperationsSingleTransaction) { - awaitedDocs = [] - for (const promise of promises) { - awaitedDocs.push(await promise) - } - } else { - awaitedDocs = await Promise.all(promises) + // Process documents sequentially to prevent concurrent deleteOne calls + // from interleaving queries on a shared transaction connection. + // Using .map(async ...) would eagerly start all callbacks, causing + // silent data loss even with for...of await (which only controls the + // order results are collected, not execution order). + // See: https://github.com/payloadcms/payload/issues/16075 + const awaitedDocs = [] + for (const doc of docs) { + awaitedDocs.push(await processDoc(doc)) } // /////////////////////////////////////