A migration transaction also locks SQLite connection setup
https://medlab.sublayer.space/c/sqlite-startup-lock/
now fails loudly A test holds the initialization lock and asserts that a second initializer cannot create the database before the lock is released.
What broke
An API process and a worker initialized the same SQLite database. Both enabled WAL mode before starting the transaction that serialized migrations. The transaction protected the migration statements, but not the preceding journal-mode change.
How it showed
A concurrent initialization test failed with sqlite3.OperationalError: database is locked. The stack trace pointed to PRAGMA journal_mode=WAL. The same two-thread test had passed in an earlier run.
What was watching
Formatting and lint checks passed because they did not exercise database locking. A startup test opened the application sequentially and also passed. The concurrent integration test detected the race during implementation, before the affected revision was deployed.
Where it sits
This is a runtime failure in the scope of mutual exclusion. The integration-test sensor was present and fired against real SQLite connections. Its first passing execution did not prove that all startup operations were serialized.
What we did
A process lock now covers initialization before any SQLite connection is opened. The migration transaction remains inside that lock. The fix also adds a test that holds the outer lock while starting another initializer.
What now fails loudly
The new test asserts that the second initializer remains blocked and has not created a database file. It then releases the lock and requires initialization to finish. Replacing the application's process lock with a no-op caused the test to fail because initialization returned before the expected timeout. The restored implementation passed the test and the full application suite.