[Bug]: Slow file upload/processing speed with large library (~54k items) despite optimal config #3202

Open
opened 2026-02-20 11:01:25 -05:00 by deekerman · 4 comments
Owner

Originally created by @piotr1alien-art on GitHub (Jan 25, 2026).

What happened?

File upload/processing caps at ~3-3,5 MB/s. Diagnostic steps show this is not due to CPU (Zlib off), disk I/O (iostat shows low %util), network, or reverse proxy. The bottleneck appears to be the high volume of small database I/O operations generated per file in a large library.

What did you expect to happen?

File upload/processing caps at min~16-18 MB/s.

Steps to reproduce the issue

  1. find /home/Audiobook/ | wc -l 54649

Audiobookshelf version

ABS v2.30.0/2.32.1, Debian 12, AB_ZLIB_LEVEL=0, SQLite DB on NVMe (WAL mode), library on SSD RAID.

How are you running audiobookshelf?

Debian/PPA

What OS is your Audiobookshelf server hosted from?

Linux

If the issue is being seen in the UI, what browsers are you seeing the problem on?

Firefox

Logs

Total DISK READ:         0.00 B/s | Total DISK WRITE:       237.84 K/s
Current DISK READ:       0.00 B/s | Current DISK WRITE:       8.92 K/s
    PID  PRIO  USER     DISK READ DISK WRITE>    COMMAND                                                                        
2826431 be/4 audioboo      4.00 M     12.48 M audiobookshelf

Additional Notes

No response

Originally created by @piotr1alien-art on GitHub (Jan 25, 2026). ### What happened? File upload/processing caps at ~3-3,5 MB/s. Diagnostic steps show this is not due to CPU (Zlib off), disk I/O (iostat shows low %util), network, or reverse proxy. The bottleneck appears to be the high volume of small database I/O operations generated per file in a large library. ### What did you expect to happen? File upload/processing caps at min~16-18 MB/s. ### Steps to reproduce the issue 1. find /home/Audiobook/ | wc -l 54649 ### Audiobookshelf version ABS v2.30.0/2.32.1, Debian 12, `AB_ZLIB_LEVEL=0`, SQLite DB on NVMe (WAL mode), library on SSD RAID. ### How are you running audiobookshelf? Debian/PPA ### What OS is your Audiobookshelf server hosted from? Linux ### If the issue is being seen in the UI, what browsers are you seeing the problem on? Firefox ### Logs ```shell Total DISK READ: 0.00 B/s | Total DISK WRITE: 237.84 K/s Current DISK READ: 0.00 B/s | Current DISK WRITE: 8.92 K/s PID PRIO USER DISK READ DISK WRITE> COMMAND 2826431 be/4 audioboo 4.00 M 12.48 M audiobookshelf ``` ### Additional Notes _No response_
Author
Owner

@piotr1alien-art commented on GitHub (Jan 25, 2026):

2026-01-25 14:39:46.440

FATAL

[Server] Unhandled rejection: Error at Database. (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:185:27) at /snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:183:50 at new Promise () at Query.run (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:183:12) at /snapshot/audiobookshelf/node_modules/sequelize/lib/sequelize.js:315:28 at async SQLiteQueryInterface.bulkInsert (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/abstract/query-interface.js:346:21) at async recursiveBulkCreate (/snapshot/audiobookshelf/node_modules/sequelize/lib/model.js:1697:25) at async bookAuthor.bulkCreate (/snapshot/audiobookshelf/node_modules/sequelize/lib/model.js:1786:12) at async ApiRouter.update (/snapshot/audiobookshelf/server/controllers/AuthorController.js) { name: 'SequelizeUniqueConstraintError', errors: [ ValidationErrorItem { message: 'bookId must be unique', type: 'unique violation', path: 'bookId', value: null, origin: 'DB', instance: null, validatorKey: 'not_unique', validatorName: null, validatorArgs: [] }, ValidationErrorItem { message: 'authorId must be unique', type: 'unique violation', path: 'authorId', value: null, origin: 'DB', instance: null, validatorKey: 'not_unique', validatorName: null, validatorArgs: [] } ], parent: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: bookAuthors.bookId, bookAuthors.authorId] { errno: 19, code: 'SQLITE_CONSTRAINT', sql: "INSERT INTO bookAuthors (id,createdAt,bookId,authorId) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" }, original: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: bookAuthors.bookId, bookAuthors.authorId] { errno: 19, code: 'SQLITE_CONSTRAINT', sql: "INSERT INTO bookAuthors (id,createdAt,bookId,authorId) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" }, fields: [ 'bookId', 'authorId' ], sql: "INSERT INTO bookAuthors (id,createdAt,bookId,authorId) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" } promise: Promise { Error at Database. (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:185:27) at /snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:183:50 at new Promise () at Query.run (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:183:12) at /snapshot/audiobookshelf/node_modules/sequelize/lib/sequelize.js:315:28 at async SQLiteQueryInterface.bulkInsert (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/abstract/query-interface.js:346:21) at async recursiveBulkCreate (/snapshot/audiobookshelf/node_modules/sequelize/lib/model.js:1697:25) at async bookAuthor.bulkCreate (/snapshot/audiobookshelf/node_modules/sequelize/lib/model.js:1786:12) at async ApiRouter.update (/snapshot/audiobookshelf/server/controllers/AuthorController.js) { name: 'SequelizeUniqueConstraintError', errors: [ [ValidationErrorItem], [ValidationErrorItem] ], parent: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: bookAuthors.bookId, bookAuthors.authorId] { errno: 19, code: 'SQLITE_CONSTRAINT', sql: "INSERT INTO bookAuthors (id,createdAt,bookId,authorId) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" }, original: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: bookAuthors.bookId, bookAuthors.authorId] { errno: 19, code: 'SQLITE_CONSTRAINT', sql: "INSERT INTO bookAuthors (id,createdAt,bookId,authorId) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" }, fields: [ 'bookId', 'authorId' ], sql: "INSERT INTO bookAuthors (id,createdAt,bookId,authorId) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" } }

@piotr1alien-art commented on GitHub (Jan 25, 2026): 2026-01-25 14:39:46.440 FATAL [Server] Unhandled rejection: Error at Database.<anonymous> (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:185:27) at /snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:183:50 at new Promise (<anonymous>) at Query.run (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:183:12) at /snapshot/audiobookshelf/node_modules/sequelize/lib/sequelize.js:315:28 at async SQLiteQueryInterface.bulkInsert (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/abstract/query-interface.js:346:21) at async recursiveBulkCreate (/snapshot/audiobookshelf/node_modules/sequelize/lib/model.js:1697:25) at async bookAuthor.bulkCreate (/snapshot/audiobookshelf/node_modules/sequelize/lib/model.js:1786:12) at async ApiRouter.update (/snapshot/audiobookshelf/server/controllers/AuthorController.js) { name: 'SequelizeUniqueConstraintError', errors: [ ValidationErrorItem { message: 'bookId must be unique', type: 'unique violation', path: 'bookId', value: null, origin: 'DB', instance: null, validatorKey: 'not_unique', validatorName: null, validatorArgs: [] }, ValidationErrorItem { message: 'authorId must be unique', type: 'unique violation', path: 'authorId', value: null, origin: 'DB', instance: null, validatorKey: 'not_unique', validatorName: null, validatorArgs: [] } ], parent: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: bookAuthors.bookId, bookAuthors.authorId] { errno: 19, code: 'SQLITE_CONSTRAINT', sql: "INSERT INTO `bookAuthors` (`id`,`createdAt`,`bookId`,`authorId`) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" }, original: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: bookAuthors.bookId, bookAuthors.authorId] { errno: 19, code: 'SQLITE_CONSTRAINT', sql: "INSERT INTO `bookAuthors` (`id`,`createdAt`,`bookId`,`authorId`) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" }, fields: [ 'bookId', 'authorId' ], sql: "INSERT INTO `bookAuthors` (`id`,`createdAt`,`bookId`,`authorId`) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" } promise: Promise { <rejected> Error at Database.<anonymous> (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:185:27) at /snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:183:50 at new Promise (<anonymous>) at Query.run (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/sqlite/query.js:183:12) at /snapshot/audiobookshelf/node_modules/sequelize/lib/sequelize.js:315:28 at async SQLiteQueryInterface.bulkInsert (/snapshot/audiobookshelf/node_modules/sequelize/lib/dialects/abstract/query-interface.js:346:21) at async recursiveBulkCreate (/snapshot/audiobookshelf/node_modules/sequelize/lib/model.js:1697:25) at async bookAuthor.bulkCreate (/snapshot/audiobookshelf/node_modules/sequelize/lib/model.js:1786:12) at async ApiRouter.update (/snapshot/audiobookshelf/server/controllers/AuthorController.js) { name: 'SequelizeUniqueConstraintError', errors: [ [ValidationErrorItem], [ValidationErrorItem] ], parent: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: bookAuthors.bookId, bookAuthors.authorId] { errno: 19, code: 'SQLITE_CONSTRAINT', sql: "INSERT INTO `bookAuthors` (`id`,`createdAt`,`bookId`,`authorId`) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" }, original: [Error: SQLITE_CONSTRAINT: UNIQUE constraint failed: bookAuthors.bookId, bookAuthors.authorId] { errno: 19, code: 'SQLITE_CONSTRAINT', sql: "INSERT INTO `bookAuthors` (`id`,`createdAt`,`bookId`,`authorId`) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" }, fields: [ 'bookId', 'authorId' ], sql: "INSERT INTO `bookAuthors` (`id`,`createdAt`,`bookId`,`authorId`) VALUES ('73db31a5-3de8-4551-86ef-22c1fccd5d6b','2026-01-25 13:39:46.427 +00:00','5a32c81b-5e37-4fa8-8d0c-7b40c929c245','c4c746a4-7f3e-43a3-9761-e3aa46e6c51a');" } }
Author
Owner

@piotr1alien-art commented on GitHub (Jan 25, 2026):

SQLite version 3.50.1 2025-06-06 14:52:32
Enter ".help" for usage hints.
sqlite> SELECT * FROM bookAuthors WHERE bookId='5a32c81b-5e37-4fa8-8d0c-7b40c929c245' AND authorId='c4c746a4-7f3e-43a3-9761-e3aa46e6c51a';
699899b5-7fcf-4e61-8473-2e48af7d4e36|2025-04-30 12:08:42.760 +00:00|5a32c81b-5e37-4fa8-8d0c-7b40c929c245|c4c746a4-7f3e-43a3-9761-e3aa46e6c51a
sqlite> SELECT bookId, authorId, COUNT() as count
FROM bookAuthors
GROUP BY bookId, authorId
HAVING COUNT(
) > 1; ...> ...> ...>
sqlite> .exit

@piotr1alien-art commented on GitHub (Jan 25, 2026): SQLite version 3.50.1 2025-06-06 14:52:32 Enter ".help" for usage hints. sqlite> SELECT * FROM bookAuthors WHERE bookId='5a32c81b-5e37-4fa8-8d0c-7b40c929c245' AND authorId='c4c746a4-7f3e-43a3-9761-e3aa46e6c51a'; 699899b5-7fcf-4e61-8473-2e48af7d4e36|2025-04-30 12:08:42.760 +00:00|5a32c81b-5e37-4fa8-8d0c-7b40c929c245|c4c746a4-7f3e-43a3-9761-e3aa46e6c51a sqlite> SELECT bookId, authorId, COUNT(*) as count FROM bookAuthors GROUP BY bookId, authorId HAVING COUNT(*) > 1; ...> ...> ...> sqlite> .exit
Author
Owner

@nichwall commented on GitHub (Jan 25, 2026):

I'm confused, is this with scanning a brand new library of 54000 books or uploading a single book to an existing 54000 book library?

@nichwall commented on GitHub (Jan 25, 2026): I'm confused, is this with scanning a brand new library of 54000 books or uploading a single book to an existing 54000 book library?
Author
Owner

@piotr1alien-art commented on GitHub (Jan 25, 2026):

In my case, it's about uploading/updating a single book to an already existing large library (~54k items).

It seems like a race condition or a lack of proper "upsert" logic. I’ve caught a SequelizeUniqueConstraintError in the logs. Even though the system resources are underutilized, the server throws a FATAL error because it tries to INSERT a bookId and authorId pair that already exists in the SQLite database, instead of ignoring or updating it.

Here is the specific error from my logs: SQLITE_CONSTRAINT: UNIQUE constraint failed: bookAuthors.bookId, bookAuthors.authorId

When I checked the database manually: SELECT * FROM bookAuthors WHERE bookId='...' AND authorId='...'; The entry was already there (created months ago), but the upload process tried to recreate it with a new ID, crashing the server.

@piotr1alien-art commented on GitHub (Jan 25, 2026): In my case, it's about uploading/updating a single book to an already existing large library (~54k items). It seems like a race condition or a lack of proper "upsert" logic. I’ve caught a SequelizeUniqueConstraintError in the logs. Even though the system resources are underutilized, the server throws a FATAL error because it tries to INSERT a bookId and authorId pair that already exists in the SQLite database, instead of ignoring or updating it. Here is the specific error from my logs: SQLITE_CONSTRAINT: UNIQUE constraint failed: bookAuthors.bookId, bookAuthors.authorId When I checked the database manually: SELECT * FROM bookAuthors WHERE bookId='...' AND authorId='...'; The entry was already there (created months ago), but the upload process tried to recreate it with a new ID, crashing the server.
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/audiobookshelf-advplyr#3202
No description provided.