Heuristic:Promptfoo Promptfoo WAL Mode Network Filesystem
| Knowledge Sources | |
|---|---|
| Domains | Database, Debugging |
| Last Updated | 2026-02-14 08:00 GMT |
Overview
SQLite WAL mode fails silently on network filesystems (NFS, CIFS) and some containerized environments; set `PROMPTFOO_DISABLE_WAL_MODE=true` when the database resides on non-local storage.
Description
Promptfoo enables SQLite WAL (Write-Ahead Logging) mode by default for better concurrent read/write performance. However, WAL mode requires shared memory primitives (`mmap`) that are not available on all filesystems. Network filesystems (NFS, CIFS/SMB) and some container volume mounts may fail to enable WAL, silently falling back to the slower `DELETE` journal mode. Promptfoo detects this by verifying the PRAGMA result after setting WAL mode and emits a warning if the mode was not actually applied.
Usage
Apply this heuristic when deploying promptfoo in environments where the `~/.promptfoo/` directory is on a network filesystem, a Docker volume backed by a network share, or any other non-local storage. Also relevant in CI/CD pipelines where the filesystem may have limitations.
The Insight (Rule of Thumb)
- Action: Set `PROMPTFOO_DISABLE_WAL_MODE=true` when database files are on network filesystems or constrained container volumes.
- Detection: Look for the warning message `Failed to enable WAL mode (got 'delete')` in logs.
- Trade-off: Without WAL mode, concurrent read/write performance is reduced. Reads block writes and vice versa. For single-user CLI usage this is usually acceptable.
- Additional: When WAL is enabled, `synchronous = NORMAL` is set for balanced safety/speed, and `wal_autocheckpoint = 1000` pages prevents unbounded WAL file growth.
Reasoning
From `src/database/index.ts:40-70`:
if (!isMemoryDb && !getEnvBool('PROMPTFOO_DISABLE_WAL_MODE', false)) {
try {
sqliteInstance.pragma('journal_mode = WAL');
// Verify WAL mode was actually enabled
const result = sqliteInstance.prepare('PRAGMA journal_mode').get();
if (result.journal_mode.toLowerCase() === 'wal') {
logger.debug('Successfully enabled SQLite WAL mode');
} else {
logger.warn(
`Failed to enable WAL mode (got '${result.journal_mode}'). ` +
'Database performance may be reduced. This can happen on network filesystems. ' +
'Set PROMPTFOO_DISABLE_WAL_MODE=true to suppress this warning.',
);
}
sqliteInstance.pragma('wal_autocheckpoint = 1000');
sqliteInstance.pragma('synchronous = NORMAL');
} catch (err) {
logger.warn(
`Error configuring SQLite WAL mode: ${err}. ` +
'Database will use default journal mode. Performance may be reduced. ' +
'This can happen on network filesystems or certain containerized environments. ' +
'Set PROMPTFOO_DISABLE_WAL_MODE=true to suppress this warning.',
);
}
}
The verification step (checking PRAGMA result after setting) is the key defensive pattern. Without this, WAL failure is completely silent in SQLite, and performance degrades with no diagnostic clue.