Twee projecten waar ik nu aan bouw, draaien op Cloudflare. SF Sales Solutions is een carrièresite en beheerapp voor een salesrecruiter, met Astro, React, Workers en D1. Tradi is een website voor een herenmode-agentuur, met Astro en Workers. Beide zijn nog in uitvoering, dus over resultaten schrijf ik hier niets.
De cijfers hieronder zijn die van de documentatie van Cloudflare op het moment van schrijven. Controleer de limieten van Workers en die van D1 voor je erop rekent.
Wat een Worker is
Een Worker is een stuk JavaScript of TypeScript dat op het netwerk van Cloudflare draait, in een V8-isolate. Een isolate start veel sneller dan een container, en er is geen server die je moet beheren. Je code reageert op een verzoek en werkt met webstandaarden zoals fetch, Request en Response.
Andere diensten bereik je via bindings. Die declareer je in je configuratie, en ze komen als env in je code terecht. Je hoeft geen verbindingsgegevens te beheren.
# Vereenvoudigde illustratie
name = "voorbeeld"
main = "src/index.ts"
compatibility_date = "2026-10-01"
compatibility_flags = ["nodejs_compat"]
[[d1_databases]]
binding = "DB"
database_name = "voorbeeld"
database_id = "..."
Astro past daar goed bij. Met de Cloudflare-adapter render je vooraf wat statisch kan, en draait de rest als Worker. React gebruik je dan alleen op de stukken die het nodig hebben, zoals een beheerscherm.
Waar Workers sterk in zijn
Er valt weinig te beheren. wrangler deploy zet je code online, zonder servers om te patchen of capaciteit om te plannen. Je code draait dicht bij de bezoeker, wat vooral helpt voor wat geen databank nodig heeft. Lokaal ontwikkelen gebeurt met dezelfde runtime als in productie.
Je hebt ook alles in één configuratie zitten: D1 voor SQL, R2 voor bestanden, Queues voor werk op de achtergrond en Cron Triggers voor geplande taken. Voor een site met formulieren en een klein beheerscherm is dat meestal genoeg.
Waar Workers stoppen
CPU-tijd is beperkt per verzoek. Wachten op I/O telt niet mee, rekenen wel. Op het betaalde plan kan je de limiet verhogen, en op het gratis plan is ze heel krap.
Een isolate heeft 128 MB geheugen, en één isolate kan meerdere verzoeken tegelijk bedienen. Een variabele op moduleniveau wordt dus gedeeld tussen verzoeken, en daar bewaar je niets dat bij één gebruiker hoort.
De runtime is geen Node. Met nodejs_compat werkt een groot deel van de Node-API’s, maar er is geen gewoon bestandssysteem, en pakketten met native modules draaien niet. Controleer dat vroeg als je afhankelijk bent van een bibliotheek voor bijvoorbeeld pdf’s of beeldverwerking.
Werk na het antwoord kan met ctx.waitUntil, maar dat heeft een korte limiet. Lange taken horen in een queue of een Workflow.
Wat D1 is
D1 is een beheerde databank op basis van SQLite. Je bereikt ze via een binding, met prepared statements, en je beheert het schema met wrangler d1 migrations. Met batch voer je meerdere statements uit als één transactie: faalt er een, dan wordt het geheel teruggedraaid.
// Vereenvoudigde illustratie, niet de code van een klantproject.
export default {
async fetch(request: Request, env: Env): Promise<Response> {
const form = await request.formData();
const id = crypto.randomUUID();
await env.DB.batch([
env.DB.prepare("INSERT INTO signups (id, name, email) VALUES (?, ?, ?)")
.bind(id, form.get("name"), form.get("email")),
env.DB.prepare("INSERT INTO audit_log (signup_id, action) VALUES (?, 'created')")
.bind(id),
]);
return Response.json({ id }, { status: 201 });
},
};
Waar D1 stopt
Een D1-databank is single-threaded en verwerkt één query tegelijk. De doorvoer hangt dus rechtstreeks af van hoe lang je queries duren, en een trage query houdt alle andere op. Je indexen bepalen hier mee hoeveel verkeer de databank aankan.
Op het betaalde plan kan een databank maximaal 10 GB groot worden, op het gratis plan 500 MB, en de grens van 10 GB kan je niet laten verhogen. D1 is gemaakt om uit te breiden over veel kleinere databanken, bijvoorbeeld één per klant. Een groot gedeeld schema past daar minder goed bij.
Een batch is een vaste lijst statements. Je kan geen transactie openhouden terwijl je in je code iets leest, beslist en dan schrijft. Vaak los je dat op in de SQL zelf, met ON CONFLICT of een UPDATE met een versie in de WHERE.
Een databank heeft één primaire locatie. Een Worker ver daarvandaan betaalt voor die afstand bij elke query, dus snelheid aan de rand van het netwerk telt minder zodra je de databank nodig hebt. Met read replication en de Sessions API kunnen leesacties naar een replica gaan, terwijl schrijfacties naar de primaire blijven gaan.
Bouw je voor klanten in Europa, dan wil je weten waar de data staat. Een location hint is alleen een voorkeur. Een jurisdictie, zoals eu, houdt de databank en haar replica’s binnen die regio, en dat moet je instellen bij het aanmaken, want achteraf kan het niet meer. De Worker zelf kan nog altijd overal draaien. Wat dat juridisch betekent voor jouw project, leg je best voor aan een jurist.
Voor welk project het past
De combinatie past bij sites met vooral leesverkeer en formulieren, en bij kleine beheerschermen met een overzichtelijke hoeveelheid data. Bij data die je per klant kan opsplitsen, past D1 ook goed.
Ze past minder bij veel gelijktijdige schrijfacties in één databank, grote analytische queries, zwaar rekenwerk of bibliotheken die op Node leunen. Workers kunnen dan nog altijd het voorste stuk doen. Met Hyperdrive bereik je vanuit een Worker een bestaande Postgres-databank.
Lees ook
Wat is jouw idee?
Vertel me wat je wil bouwen. Ik probeer binnen één werkdag te antwoorden.