Performance Differences Between Native SQLite and WASM Backends in CodeGraph
Native SQLite via better-sqlite3 runs 5–10× faster than the WASM fallback, with the latter disabling memory mapping and using DELETE journal mode for reduced I/O efficiency.
CodeGraph stores its knowledge graph in an SQLite database and automatically selects between a native C extension and a WebAssembly implementation based on runtime availability. Understanding the performance differences between native SQLite and WASM backends in CodeGraph is critical for developers optimizing indexing speed and incremental sync operations on large codebases.
Backend Selection Architecture
At initialization, CodeGraph attempts to load the native better-sqlite3 driver first. If the compiled binary fails to load—typically due to missing build tools or incompatible CI environments—the system falls back to the pure-JavaScript node-sqlite3-wasm implementation.
In src/db/sqlite-adapter.ts (lines 46-52), the createDatabase factory function implements this fallback logic. When the WASM path activates, the adapter prints a warning banner to stderr explicitly stating that operations will run 5–10× slower than the native backend, ensuring developers understand the performance implications immediately.
Execution Model and Throughput
The architectural differences between the two backends create dramatic performance gaps:
Native (better-sqlite3): Operates as a synchronous C extension compiled for the host platform. This implementation executes hundreds of thousands of statements per second with direct access to SQLite’s optimized memory management and platform-specific CPU instructions.
WASM (node-sqlite3-wasm): Runs as a WebAssembly module interpreted by the JavaScript engine. Every INSERT, SELECT, and PRAGMA call incurs WebAssembly call overhead and boundary crossing costs between JS and WASM memory spaces, resulting in the documented 5–10× throughput reduction highlighted in the source code comments.
Resource Utilization and Journal Modes
Beyond raw execution speed, the backends differ fundamentally in I/O efficiency. In src/db/sqlite-adapter.ts (lines 77-85), the WASM adapter explicitly configures the database with constraints that reduce performance:
- DELETE journal mode instead of the high-performance WAL (Write-Ahead Logging) mode used by native SQLite
- Disabled memory mapping (mmap) support, forcing all database I/O through standard read/write operations rather than direct memory access
These constraints significantly reduce I/O efficiency during large-scale indexing operations, exacerbating the throughput limitations of the WebAssembly interpreter.
Impact on CodeGraph Workflows
The backend selection directly affects two primary CodeGraph operations where database throughput is critical:
Full Indexing (codegraph index): The WASM backend processes bulk INSERT operations significantly slower. Projects that index in seconds with the native driver may require tens of seconds or minutes under WASM due to the combination of execution overhead and DELETE journal mode disk I/O.
Incremental Sync (codegraph sync): Each batch of changes incurs the same WebAssembly call overhead during incremental updates. developers running frequent sync operations on large codebases will notice substantially slower iteration cycles when the WASM backend is active.
Detecting Your Active Backend
To determine which SQLite implementation is currently active, inspect the backend property exposed by the database connection instance:
import { CodeGraph } from 'codegraph';
const cg = await CodeGraph.init('/path/to/project');
// Query which SQLite backend is currently in use
const { backend } = cg.db; // DatabaseConnection defined in src/db/index.ts
console.log(`Active backend: ${backend}`);
// Output: "Active backend: native" or "Active backend: wasm"
When the native driver loads successfully, backend returns "native". If the system falls back to WebAssembly, it returns "wasm" and triggers the performance warning banner.
CLI Status Verification
Alternatively, use the command-line interface to verify backend status:
codegraph status
This command (implemented in src/bin/codegraph.ts) reports the active backend alongside other database statistics. If you observe Backend: wasm in the output, expect indexing and sync operations to run several times slower than the native baseline.
Restoring Native Performance
The WASM fallback activates when better-sqlite3 fails to load, typically due to missing Python, C++ build tools, or compilation errors during installation. To restore native performance:
- Install platform-specific build dependencies (Python, C++ compiler, and node-gyp requirements)
- Reinstall
better-sqlite3to trigger native binary compilation - Verify via
codegraph statusthat the output showsBackend: native
The unit tests in __tests__/sqlite-backend.test.ts validate this fallback path and confirm that the performance-related warning emits correctly when the WASM adapter initializes.
Summary
- Native SQLite (
better-sqlite3) provides synchronous C-extension performance with WAL journaling and memory mapping, handling hundreds of thousands of statements per second. - WASM SQLite (
node-sqlite3-wasm) runs 5–10× slower due to WebAssembly interpretation overhead, forcing DELETE journal mode and disabling mmap for reduced I/O efficiency. - CodeGraph automatically selects backends in
src/db/sqlite-adapter.ts, warning users when the slower WASM fallback activates via console output. - Check your active backend via
cg.db.backendor thecodegraph statusCLI command; native restoration requires proper build tools for recompilingbetter-sqlite3.
Frequently Asked Questions
How much slower is the WASM backend compared to native SQLite in CodeGraph?
The WASM backend runs 5–10× slower than the native implementation. This performance degradation is documented in the warning banner at src/db/sqlite-adapter.ts (lines 49-51) and manifests during both bulk indexing operations and incremental sync cycles due to WebAssembly call overhead and disabled memory mapping.
Why does the WASM backend disable WAL mode and memory mapping?
In src/db/sqlite-adapter.ts (lines 77-85), the WASM adapter explicitly configures DELETE journal mode instead of WAL and disables mmap because the WebAssembly runtime lacks efficient support for the shared memory mapping primitives required by SQLite’s high-performance modes. This configuration reduces I/O efficiency but ensures compatibility across all JavaScript environments.
How can I check which SQLite backend CodeGraph is currently using?
Access the backend property on the database connection instance (cg.db.backend) after initializing CodeGraph, or run codegraph status from the terminal. The property returns "native" when using better-sqlite3 or "wasm" when using the fallback implementation, as defined in src/db/index.ts.
What causes CodeGraph to fall back to the WASM implementation?
The fallback occurs when the native better-sqlite3 binary fails to load, typically on systems without C++ build tools, Python, or compatible compilation environments. The factory function in src/db/sqlite-adapter.ts catches these load failures and automatically instantiates the WasmDatabaseAdapter, printing a performance warning to stderr during initialization.
Have a question about this repo?
These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:
curl -s "https://instagit.com/install.md" Maintain an open-source project? Get it listed too →