From 9362044cc52f35f1a704c49a9a14f4c8c1013779 Mon Sep 17 00:00:00 2001 From: mboyd1 Date: Wed, 25 Mar 2026 09:11:39 -0500 Subject: [PATCH] fix: prevent SQLITE_BUSY by limiting to single connection SetMaxOpenConns(1) serializes writes through one connection, eliminating SQLITE_BUSY errors under concurrent HTTP load. Also adds cache_size, mmap_size, and temp_store pragmas for better throughput. Co-Authored-By: Claude Opus 4.6 (1M context) --- store/sqlite/sqlite.go | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/store/sqlite/sqlite.go b/store/sqlite/sqlite.go index a7aa6c6..2babb86 100644 --- a/store/sqlite/sqlite.go +++ b/store/sqlite/sqlite.go @@ -18,11 +18,14 @@ import ( ) const ( - // SQLite pragmas for better concurrency + // SQLite pragmas for better concurrency and throughput sqlitePragmas = ` PRAGMA journal_mode=WAL; PRAGMA busy_timeout=5000; PRAGMA synchronous=NORMAL; +PRAGMA cache_size=-64000; +PRAGMA mmap_size=268435456; +PRAGMA temp_store=MEMORY; ` ) @@ -38,6 +41,11 @@ func NewStore(dbPath string) (*Store, error) { return nil, fmt.Errorf("failed to open database: %w", err) } + // SQLite only allows one writer at a time. Limiting to a single connection + // prevents SQLITE_BUSY errors under concurrent HTTP load. WAL mode still + // allows concurrent reads from this connection while a write is in progress. + db.SetMaxOpenConns(1) + if _, err := db.ExecContext(context.Background(), sqlitePragmas); err != nil { return nil, fmt.Errorf("failed to set pragmas: %w", err) }