Amikor egy kisebb backendhez vagy egy CLI eszközhöz csak egy egyszerű, fájlalapú adatbázis kell, a Node.js-es fejlesztők évek óta a better-sqlite3 csomagot telepítik. Ez mostantól egyre kevésbé indokolt: a node:sqlite beépített modul 2026 elején elérte a release candidate stabilitást a Node.js 24-es és 25-ös ágában is, ami a Node stabilitási index szerint azt jelenti, hogy a build már nem fog összeomlani a lábad alatt egy minor frissítéstől.

Rövid történet: flagtől a release candidate-ig
A modul nem új: a Node.js 22.5.0 hozta el --experimental-sqlite flag mögé rejtve. A 22.13.0 és a 23.4.0 már flag nélkül is engedte használni, de a figyelmeztetés (ExperimentalWarning) maradt. A következő komoly mérföldkő a Node stabilitási indexe szerinti „1.2 – Release candidate” besorolás volt, amit a 24.15.0-s (LTS, 2026. április) és a 25.7.0-s release hozott el. A dokumentáció szó szerint ezt írja erről a szintről:
„Release candidate. Ezen a szinten a kísérleti funkciók remélhetőleg készen állnak arra, hogy stabillá váljanak. Nem várunk további, kompatibilitást törő módosítást, bár ez a felhasználói visszajelzések vagy a mögöttes specifikáció változása miatt még előfordulhat.”
Ez lényegesen több biztonságot ad, mint egy sima „experimental” jelzés – de a figyelmeztető üzenet a konzolon még mindig ott van (a Node 22-es LTS-ben is), és API-törés még becsúszhat, ha valami komoly probléma derül ki.
Hogyan néz ki a kódban
Az API magja két osztály: DatabaseSync és StatementSync. Aki már használt better-sqlite3-at, azonnal otthon érzi magát – ez itt szó szerint futó kód:
import { DatabaseSync } from 'node:sqlite';
const db = new DatabaseSync(':memory:');
db.exec(`
CREATE TABLE posts (
id INTEGER PRIMARY KEY AUTOINCREMENT,
title TEXT NOT NULL,
views INTEGER DEFAULT 0
) STRICT
`);
const insert = db.prepare('INSERT INTO posts (title, views) VALUES (?, ?)');
insert.run('Bevezetés a node:sqlite-be', 120);
insert.run('WAL mode és konkurencia', 45);
const select = db.prepare(
'SELECT * FROM posts WHERE views > ? ORDER BY views DESC'
);
console.log(select.all(40));
// [
// { id: 1, title: 'Bevezetés a node:sqlite-be', views: 120 },
// { id: 2, title: 'WAL mode és konkurencia', views: 45 }
// ]
Nincs npm install, nincs natív bindinget fordító node-gyp, nincs platformfüggő prebuild letöltés CI-ben. A STRICT táblakulcsszó mellesleg egy régebbi, de kevésbé ismert SQLite-funkció: kikényszeríti a deklarált oszloptípusokat, míg alapból a SQLite majdnem bármit beenged bármelyik oszlopba.
A null-prototype meglepetés
Van egy apróság, amibe garantáltan bele fogsz futni, ha éles kódban kezdi el használni: a visszaadott sorok nem sima objektumok, hanem null-prototípusúak.
const row = db.prepare('SELECT * FROM posts WHERE id = 1').get();
console.log(row);
// [Object: null prototype] { id: 1, title: 'Bevezetés a node:sqlite-be', views: 120 }
row.hasOwnProperty('id'); // TypeError: row.hasOwnProperty is not a function
JSON.stringify(row); // '{"id":1,"title":"...","views":120}' – ez működik
Ennek van értelme: egy oszlopot elnevezhetnél constructor-nak vagy toString-nak is, egy sima objektumnál ez ütközne az Object.prototype mezőivel. Null prototípusnál ilyen konfliktus nem lehet. A JSON.stringify, a Object.keys és a property-elérés (row.title) simán működik, csak az Object.prototype-ról öröklött metódusok (hasOwnProperty, toString) hiányoznak – ha ilyet hívnál egy lekért soron, robbanás lesz belőle.
Szinkron API – tudatos döntés, nem hiányosság
A node:sqlite-nak nincs Promise-alapú felülete: minden hívás blokkol, amíg a lekérdezés le nem fut. Ez local, fájlalapú adatbázisnál általában mikroszekundumos művelet, tehát az event loopot nem terheli meg jobban, mint egy szinkron JSON.parse. Nagyobb, sok írást generáló, sok egyidejű kliens által ütött szerver esetén viszont ez pont az, amiért a node:sqlite nem helyettesíti a Postgres-t vagy a MySQL-t: minden query a fő szálon fut, worker thread-ek közt kézzel kellene szétosztani a terhelést.
Konkurens olvasás/írás esetén viszont van egy régi, de sokak által kihagyott SQLite-kapcsoló, ami sokat javít: a WAL (write-ahead logging) journal mód. Alapból a SQLite minden írásnál lezárja az egész fájlt; WAL módban az olvasók nem blokkolják egymást, és egy író sem blokkolja az olvasókat, csak a többi írót.
const db = new DatabaseSync('/tmp/app.db');
db.exec('PRAGMA journal_mode = WAL');
db.prepare('PRAGMA journal_mode').get();
// { journal_mode: 'wal' }
Ez egyszeri beállítás fájlonként (perzisztens módon íródik az adatbázisfájlba), és a legtöbb single-writer/multi-reader webalkalmazás-mintára önmagában sokat old meg a konkurenciából.
Biztonsági szempontból is történt előrelépés: a 24.14.0-tól (2026. február) alapból bekapcsolt „defensive” mód letiltja azokat az SQL-funkciókat, amelyekkel egy rosszul megbízott lekérdezés (pl. felhasználói bemenetből épített SQL) elméletileg megkerülhetné a triggereket vagy sérülést okozhatna az adatbázisfájlban. Ehhez hasonlóan a loadExtension() is alapból tilos, és csak explicit allowExtension: true mellett engedélyezhető a DatabaseSync konstruktorában – tehát egy véletlenül bemásolt, harmadik féltől kapott extension nem fut le csak azért, mert valahol elérhető a fájlrendszeren.
Mikor éri meg, és mikor nem
- Igen: CLI-eszközök helyi állapottárolása, edge/serverless függvények kis, olvasás-dominált adathalmazokhoz, tesztfixture-ök és integrációs tesztek gyors, izolált adatbázisokkal, kisebb belső admin eszközök, Electron-szerű desktop appok.
- Talán még nem: ha extension-öket (pl.
sqlite-vec, FTS5 harmadik féltől) vagy egyedi SQLite build-et igényelsz, és a natív csomag ezt már most kényelmesebben megoldja. - Nem: sok egyidejű írót kiszolgáló, klasszikus többfelhasználós webes backend – ott marad a kliens/szerver adatbázis.
A release candidate státusz azt jelenti, hogy a csapat szerint az API nagyjából a végleges formáját érte el – érdemes most kísérletezni vele, mielőtt a következő projektben alapból a better-sqlite3-hoz nyúlnál. A design körüli döntéseket és a felhasználói visszajelzéseket egyébként a kezdetektől nyilvánosan, a nodejs/node #53264 issue-ban vitatta a core csapat – érdemes végigolvasni, ha érdekel, milyen trade-offokat dobtak el útközben (pl. saját aszinkron wrapper a core-ban).
Források
- Node.js – SQLite (hivatalos dokumentáció)
- Node.js – Stabilitási index
- nodejs/node PR #61262 – sqlite: mark as release candidate
- Node.js v24.15.0 release notes
- nodejs/node PR #61266 – sqlite: enable defensive mode by default
- SQLite – Write-Ahead Logging
- better-sqlite3 (GitHub)
- nodejs/node #53264 – Expose SQLite?