This guide compares @photostructure/sqlite with the alternatives to help you choose the right SQLite library for Node.js.
@photostructure/sqlite when you want:node:sqlite requires Node.js 22.5.0+node:sqlitenode:sqlite when you're readybetter-sqlite3 when you want:sqlite3
sqlite3(node-sqlite3) is unmaintained and deprecated as of December 2025. New projects should not use it. Existing users should migrate to one of the alternatives above.
node:sqlite when you're:node:sqlite, Node.js built-in moduleThe official SQLite module included with Node.js 22.5.0+. Promoted to Release Candidate (Stability: 1.2) in Node.js v25.7.0.
node:sqlite availability by Node.js version:
| Node.js | node:sqlite status |
|---|---|
| v20 | Not available |
| v22.5.0–22.12.x | Requires --experimental-sqlite flag |
| v22.13.0+ | Experimental (no flag needed, prints warning) |
| v24.0.0+ | Experimental (no flag needed, prints warning) |
| v25.0.0–25.6.x | Experimental (no flag needed, prints warning) |
| v25.7.0+ | Release Candidate (Stability: 1.2, no warning) |
Pros:
Cons:
Best for: Projects already on Node.js 22.5.0+ that want zero dependencies and are comfortable with a release-candidate API.
better-sqlite3A well-established synchronous SQLite library, now in maintenance mode (SQLite version updates and prebuild maintenance only)
Pros:
Cons:
Best for: Existing users who are happy with the current API and don't need new features.
sqlite3 (deprecated)The original asynchronous SQLite binding for Node.js, unmaintained since December 2025
Status:
Historical context:
Recommendation: Migrate to @photostructure/sqlite, better-sqlite3, or node:sqlite. See migration guide below.
| Feature | @photostructure/sqlite | node:sqlite | better-sqlite3 | sqlite3 |
|---|---|---|---|---|
| API Compatibility | node:sqlite | - | Custom | Custom |
| SQLite Version | Independent | Tied to Node.js release | Independent | Independent |
| Min Node.js Version | 20.0.0 | 22.5.0 | 14.0.0 | 10.0.0 |
| Experimental Flag | ✅ Never needed | ⚠️ Required on 22.5–22.12; not needed since 22.13 | ✅ Not needed | ✅ Not needed |
| Synchronous API | ✅ | ✅ | ✅ | ❌ |
| Asynchronous API | ❌ | ❌ | ❌ | ✅ |
| TypeScript Types | ✅ Built-in | ✅ Built-in | ✅ Via @types | ✅ Via @types |
| Custom Functions | ✅ | ✅ | ✅ | ✅ |
| Aggregate Functions | ✅ | ✅ | ✅ | ❌ |
| Window Functions | ✅ | ✅ | ✅ | ❌ |
| Sessions/Changesets | ✅ | ✅ | ❌ | ❌ |
| Backup API | ✅ | ✅ | ✅ Different API | ✅ |
| Extension Loading | ✅ | ✅ | ✅ | ✅ |
| Worker Threads | ✅ | ✅ | ✅ | ⚠️ Limited |
| FTS5 | ✅ | ✅ | ✅ | ✅ |
| JSON Functions | ✅ | ✅ | ✅ | ✅ |
| R*Tree | ✅ | ✅ | ✅ | ✅ |
| Prebuild Strategy | Bundled in npm | N/A (built-in) | Downloaded on install | Downloaded on install |
| Node-API | ✅ | N/A | ❌ V8-specific | ✅ |
| Disposable Interface | ✅ Native C++ | ✅ Native C++ | ❌ | ❌ |
| node_modules Size | ~28MB (all prebuilds) | 0 (built-in) | ~14MB (with deps) | ~15MB (with deps) |
All synchronous libraries (@photostructure/sqlite, node:sqlite, better-sqlite3) offer similar performance:
The async sqlite3 library was slower due to:
Note: sqlite3 is deprecated and unmaintained as of December 2025.
Both node:sqlite and @photostructure/sqlite provide SQLTagStore for cached prepared statements via tagged template literals. Node.js implements this in native C++, while we use a TypeScript implementation. Benchmarks show equivalent performance:
| Scenario | @photostructure/sqlite | node:sqlite | Difference |
|---|---|---|---|
| Single query cache hit | 141,000 ops/s | 155,000 ops/s | -9% |
| Multi-pattern workload | 65,000 ops/s | 50,000 ops/s | +31% |
| Write operations | 720 ops/s | 720 ops/s | 0% |
The TypeScript implementation performs equivalently because SQLite execution time dominates over cache lookup overhead. V8's Map is highly optimized for string keys, matching or exceeding native LRU performance for typical workloads.
Run npm run bench:tagstore in the benchmark/ directory to reproduce these results.
node:sqlite to @photostructure/sqlite// Just change the import - everything else stays the same!
// From: import { DatabaseSync } from 'node:sqlite';
import { DatabaseSync } from "@photostructure/sqlite";
better-sqlite3 to @photostructure/sqliteSee our detailed migration guide. Key differences:
enhance() for .transaction() and .pragma() helper methods.name → .location())sqlite3 to @photostructure/sqliteNote: sqlite3 is deprecated and unmaintained as of December 2025. Migration is strongly recommended.
Requires rewriting from async to sync patterns:
// sqlite3 (async)
db.get("SELECT * FROM users WHERE id = ?", [id], (err, row) => {
if (err) handleError(err);
else processUser(row);
});
// @photostructure/sqlite (sync)
try {
const row = db.prepare("SELECT * FROM users WHERE id = ?").get(id);
processUser(row);
} catch (err) {
handleError(err);
}
node:sqlite compatibilityChoose based on your specific needs:
node:sqlite