Does SQLite Work With Cloudflare Pages?
SQLite works with Cloudflare Pages, but only in serverless functions (Workers) with constraints—not natively on the static hosting layer.
Quick Facts
How SQLite Works With Cloudflare Pages
SQLite can be used with Cloudflare Pages through Cloudflare Workers, which power Pages Functions. However, there's a critical limitation: Workers run in V8 isolates without persistent filesystem access, so you can't use traditional SQLite bindings directly. Instead, you'll use sql.js (a JavaScript port of SQLite) or Cloudflare's D1 product, which is a managed SQL database purpose-built for Workers. If you choose sql.js, the database exists in-memory or can be serialized to/from storage, making it suitable for read-heavy, low-concurrency applications. For production applications with persistence requirements, D1 is the recommended path—it's essentially managed SQLite with global replication. Your Pages Functions can call Workers functions that query D1, creating a viable serverless SQL stack. The developer experience is smooth if you accept the architectural constraints: no traditional file-based persistence, eventual consistency across regions, and pricing based on request volume rather than storage.
Best Use Cases
Using D1 with Pages Functions
npm install --save-dev wrangler @cloudflare/workers-types// functions/api/posts.ts
export const onRequest: PagesFunction<{ DB: D1Database }> = async (context) => {
const { request, env } = context;
if (request.method === 'GET') {
const { results } = await env.DB.prepare(
'SELECT id, title, slug FROM posts ORDER BY created_at DESC LIMIT 10'
).all();
return new Response(JSON.stringify(results), {
headers: { 'Content-Type': 'application/json' },
});
}
if (request.method === 'POST') {
const { title, slug } = await request.json();
const { success } = await env.DB.prepare(
'INSERT INTO posts (title, slug) VALUES (?, ?'
).bind(title, slug).run();
return new Response(JSON.stringify({ success }), { status: 201 });
}
};
// wrangler.toml
[[env.production.d1_databases]]
binding = "DB"
database_name = "pages-db"
database_id = "your-database-id"Known Issues & Gotchas
SQLite file persistence doesn't work in Workers—no filesystem access in isolates
Fix: Use Cloudflare D1 for persistence, or use sql.js with in-memory storage for read-only/cache use cases
sql.js has performance overhead; loading large databases into memory is slow
Fix: Keep databases under 10MB, use D1 for larger datasets, or implement pagination/filtering at query time
Cold starts and execution time limits (default 10ms for free tier, up to 50ms paid) may cause timeouts
Fix: Optimize queries, use indexes, consider caching results, upgrade to higher plan if needed
D1 is in public beta and pricing/features may change
Fix: Monitor Cloudflare announcements; maintain abstraction layer in code for easy migration if needed
Alternatives
- •Cloudflare Pages + Cloudflare Workers KV (key-value store, faster but schema-less)
- •Vercel + Neon PostgreSQL (traditional serverless SQL, larger ecosystem)
- •Netlify + Supabase (managed PostgreSQL with real-time subscriptions)
Resources
Related Compatibility Guides
Explore more compatibility guides