Cloudflare D1: SQLite at the Edge Without Spending a Euro

Programming· 5 min read

Cloudflare D1: SQLite at the Edge Without Spending a Euro

The Problem It Solves

When I started building applications with Cloudflare Workers, I faced a classic dilemma: I needed a database, but most solutions forced me to choose between:

  • **Traditional databases**: High latency, predictable but expensive costs
  • **Serverless SQL**: Good latency, but prices that scale quickly
  • **NoSQL**: Fast, but locks you into a specific ecosystem

Enter D1. And it changed how I think about databases at the edge.

D1 is SQLite running directly on Cloudflare's network. It's not a theoretical concept. It's real, it works, and you can start for free.

Why D1 is Different

SQLite was always considered "development-only". But Cloudflare distributed it globally. Now you have:

  • **Read and write at the edge**: Your database is close to your users
  • **Read replicas at no cost**: Distribute read traffic without paying extra
  • **Generous free tier**: Build real applications without a credit card
  • **Native multi-tenant pattern**: Perfect for SaaS that want to scale without complexity

The magic is that SQLite is simple. You don't need to manage connection pooling, complex replication, or manual backups. Cloudflare handles it.

How It Works in Practice

Here's the important part: stop reading theory and see code.

Create a Database

```bash npx wrangler d1 create my-database ```

That's it. Cloudflare creates a SQLite instance and gives you credentials.

Connect from a Worker

```typescript export default { async fetch(request, env) { const db = env.DB; // Injected automatically

const users = await db .prepare('SELECT id, email FROM users WHERE active = ?') .bind(true) .all();

return Response.json(users); } }; ```

Note: No explicit connection. No pooling. Just call the method and it works. Cloudflare handles distribution automatically.

Real Multi-Tenant Pattern

This is where D1 shines. Imagine you're building a SaaS for small Spanish businesses. Each customer needs isolated data.

With D1, you can do this:

```typescript export default { async fetch(request, env) { const { tenantId } = request.params; const db = env.DB;

// Each tenant has its logical table const data = await db .prepare(` SELECT * FROM data WHERE tenant_id = ? AND created_at > datetime('now', '-30 days') `) .bind(tenantId) .all();

return Response.json(data); } }; ```

The read happens at the edge closest to the user. If your customer is in Barcelona, the read replica serves from there. No unnecessary latency.

Read Replicas That Cost Nothing

This is the part that surprised me when I tested it.

Cloudflare lets you create read replicas on the free tier. This means:

  • **Centralized writes**: All go to the primary database
  • **Distributed reads**: Served from nearby replicas
  • **No manual synchronization**: Cloudflare does it for you

For read-intensive applications (dashboards, reports, searches), this is game-changing. You can serve data from multiple locations without paying extra.

```typescript // Read from replica (automatic) const results = await db.prepare('SELECT ...').all();

// Write goes to primary (automatic) await db.prepare('INSERT INTO ...').run(); ```

No different API. Cloudflare handles it internally.

When D1 Makes Sense

It's not for everything, but for many use cases it's perfect:

✅ Multi-tenant SaaS: Each customer isolated, small to medium data ✅ Content applications: Blogs, wikis, documentation with static data ✅ Dashboards and reports: Frequent reads, occasional writes ✅ Low-traffic APIs: Less than hundreds of requests per second ✅ Rapid prototyping: Need a database today, don't want to manage infrastructure

❌ Not ideal for: Millions of records, massive concurrent writes, complex data with many relationships

The Real Pricing Model

I won't invent numbers. But I can tell you how it works:

  • **Free tier**: Surprisingly generous to get started
  • **Scales with actual usage**: You pay for what you use, not provisioned capacity
  • **Read replicas**: Included at no additional cost on the free tier

For a small SaaS in Spain with dozens of customers, you probably never leave the free tier. That's unusual for infrastructure.

My Experience Building with D1

Getting D1 to production was simpler than expected.

What worked well:

  • Migrations with `wrangler d1 migrations`
  • Automatic backups (Cloudflare handles them)
  • Debugging with `wrangler d1 execute`
  • Seamless integration with Next.js and Workers

What requires attention:

  • Understanding that SQLite has limits (it's not PostgreSQL)
  • Designing schemas with read replicas in mind
  • Monitoring database size (SQLite has limits)

How to Start Today

1. Install Wrangler: `npm install -g wrangler` 2. Create a project: `wrangler init my-project` 3. Create D1: `wrangler d1 create my-db` 4. Write schema: Plain SQL, nothing special 5. Deploy: `wrangler deploy`

In 30 minutes you have a globally distributed database.

The Mindset Shift

D1 made me think differently about infrastructure.

Before: "I need a robust, replicated database server with backups" Now: "Cloudflare handles that. I focus on the product"

That's what real edge computing means. It's not just low latency. It's fewer things to manage, less operations, more time to build.

Conclusion

D1 isn't the answer for everything. But for bootstrapped SaaS, content applications, and anything running on Cloudflare Workers, it's hard to find something better.

The fact that you get free read replicas on the free tier is simply good for the ecosystem. It means you can build serious applications without investing in infrastructure from day one.

Action: If you use Cloudflare Workers, try D1 in your next project. Create a table, write some data, query from the edge. You'll see why I changed my stack.

The best infrastructure is the one you don't have to think about.