Az előző modulban láttad, hogyan tartod meg a Postgrest. Most a másik utat nézzük: a D1-et, a Cloudflare beépített SQL-adatbázisát — és főleg azt, hogy neked mikor éri meg, és mikor nem.
A D1 egy SQLite-alapú, serverless SQL-adatbázis, a platform natív része. Nincs szerver, nincs kapcsolat, nincs connection string: bindingként kötöd a Workerhez, és API-n át kérdezed. Fizetni a ténylegesen olvasott/írt sorok és a tárolt adat után fizetsz — nincs instance-óra, nincs egress díj, és üresjáratban nem kerül semmibe.
A helyes mentális modell: a D1 nem „kis Aurora". Egy adatbázis mérethatára 10 GB, a dialektus SQLite (nem Postgres!), és nincsenek Postgres-extension-ök. Cserébe olyat tud, amit az Aurora nem: egy fiókban több tízezer adatbázisod lehet, ami egészen más architektúrákat nyit meg — például tenantonként egy-egy külön adatbázist, teljes adatszeparációval. Plusz 2025 óta van EU jurisdiction opció: létrehozáskor kikötheted, hogy az adat az EU-ban maradjon (GDPR-hoz kényelmes).
{
"d1_databases": [
{ "binding": "DB", "database_name": "app-db", "database_id": "<UUID>" }
]
}
használat a Workerben / Nuxt server route-ban
// olvasás — prepared statement + bind (SQL injection ellen is)
const { results } = await env.DB
.prepare("SELECT id, name FROM products WHERE category = ?")
.bind(category)
.all();
// egyetlen sor / írás
const user = await env.DB.prepare("SELECT * FROM users WHERE id = ?")
.bind(id).first();
// batch: több statement EGY hálózati körben — és egyben tranzakció is!
const results = await env.DB.batch([
env.DB.prepare("INSERT INTO orders (user_id, total) VALUES (?, ?)").bind(uid, total),
env.DB.prepare("UPDATE inventory SET stock = stock - 1 WHERE sku = ?").bind(sku),
]);
BEGIN-t nyitni, közte alkalmazáslogikát futtatni, majd COMMIT-olni több körben. A tranzakció egysége a batch(): a benne lévő statementek sorban, atomikusan futnak, hiba esetén az egész visszagördül. A „read → döntés kódban → write" mintát így vagy batch-be gyúrod (SQL-oldali feltételekkel, WHERE-ekkel), vagy erős konzisztencia-igénynél Durable Objectbe szervezed (7. modul).ORM-fronton a Drizzle első osztályú D1-támogatással bír, a Prisma szintén ismeri — a query builder-élmény tehát megmarad, csak a dialektus SQLite.
A migrációkezelés beépített és szándékosan egyszerű: sorszámozott .sql fájlok, amiket a Wrangler tart nyilván egy meta-táblában:
npx wrangler d1 migrations create app-db add_orders_table
# → migrations/0003_add_orders_table.sql — megírod az SQL-t
npx wrangler d1 migrations apply app-db --local # lokális SQLite-on (wrangler dev-hez)
npx wrangler d1 migrations apply app-db --remote # élesben
Drizzle-lel dolgozva a drizzle-kit generate által készített, mappánkénti layoutot a migrations_pattern konfiggal (pl. "migrations/*/migration.sql") közvetlenül eteted a wrangler d1 migrations apply-nak. Lokálisan a D1 egy igazi SQLite-fájl a gépeden (.wrangler/state) — gyors, offline, és nyugodtan törölhető/újraépíthető.
Aurora-világban a read replikákat te konfigurálod, és az appod dönti el, melyik endpointra megy. A D1-nél a Cloudflare automatikusan tart read replikákat több régióban, extra költség nélkül — a te dolgod csak a konzisztencia kezelése, erre való a Sessions API. A lényeg: egy session-ön belül a lekérdezések szekvenciálisan konzisztensek (sosem látsz „visszafelé ugró" adatot), a sessionök közti folytonosságot pedig egy bookmark token biztosítja, amit pl. HTTP headerben adsz körbe:
// a kliens visszaküldi az előző válasz bookmarkját
const bookmark = request.headers.get("x-d1-bookmark") ?? "first-unconstrained";
const session = env.DB.withSession(bookmark);
const result = await session
.prepare("SELECT * FROM orders WHERE user_id = ?").bind(uid).run();
// az új bookmarkot visszaadjuk a következő kéréshez
response.headers.set("x-d1-bookmark", session.getBookmark() ?? "");
Ez a minta ismerős lehet: ugyanaz a „read-your-writes egy elosztott rendszerben" probléma, amit Aurora + replikák mellett appszinten oldottál meg — itt API-szinten kapod készen.
A D1 minden változást verzióz: a Time Travel funkcióval az adatbázist visszaállíthatod egy múltbeli időpontra (30 napig visszamenőleg a fizetős csomagban) — külön backup-konfiguráció nélkül. Ez az RDS snapshot + point-in-time-restore megfelelője, csak nulla beállítással. Emellett van sima SQL-export (wrangler d1 export) — az adatod nem záródik be.
| Szempont | Hyperdrive + Postgres (Aurora) | D1 |
|---|---|---|
| Dialektus, képességek | teljes Postgres: extension-ök, tárolt eljárások, ablakfüggvények mindenestül | SQLite: erős alap-SQL, JSON-függvények, FTS — de nincs pgvector, PostGIS & tsai |
| Tranzakciók | teljes értékű, interaktív | csak batch() (atomikus, de nem interaktív) |
| Méret | gyakorlatilag korlátlan | 10 GB / adatbázis (de tízezernyi DB lehet) |
| Üzemeltetés | Aurora-t továbbra is te fizeted/patcheled/méretezed | nulla — nincs instance, nincs karbantartási ablak |
| Költségmodell | Aurora instance-óra + tárolás + Hyperdrive (Workers Paid része) | olvasott/írt sorok + tárolás; üresjáratban ~0 Ft |
| Read-skálázás | Aurora replikák (te konfigurálod) | automatikus replikák + Sessions API |
| Tipikus eset nálad | a fő, meglévő üzleti adatbázis | új, jól körülhatárolt feature-ök; per-tenant adatok; edge-közeli kiszolgálás |
SQLite-dialektus (nincsenek Postgres-extension-ök, más SQL-felület) és a 10 GB-os per-DB határ — cserébe tízezernyi adatbázis lehet egy fiókban, ami per-tenant architektúrákat tesz természetessé.
env.DB.batch([...])-ben küldöd a két statementet: egy hálózati kör, sorban, atomikusan futnak — hiba esetén az egész visszagördül. A feltételes logikát SQL-be (WHERE stock > 0) viszed, nem app-kódba a két statement közé.
A sessionök közti logikai folytonosságra: a bookmark rögzíti, „hol tartott" az előző session, így a következő kérés (akár másik PoP-on, másik replikán) garantáltan nem lát régebbi állapotot — read-your-writes konzisztencia elosztott replikák felett.
A Time Travel — visszaállítás egy múltbeli időpontra (30 napig, paid). Semmit nem kell konfigurálni, alapból működik.
Ha a meglévő Postgres-sémád extension-ökre, interaktív tranzakciókra vagy 10 GB-nál nagyobb egybefüggő adatra épül — ilyenkor Hyperdrive + Postgres az út, a D1 erőltetése átírási kockázat valódi haszon nélkül.