DEV Community

Alex Spinov
Alex Spinov

Posted on

Cloudflare D1 Has a Free API: SQLite at the Edge with Zero Latency

What is Cloudflare D1?

Cloudflare D1 is a serverless SQL database built on SQLite, running at Cloudflare's edge network. Your database is milliseconds from your users — everywhere in the world.

Free tier: 5 GB storage, 5M reads/day, 100K writes/day.

Quick Start

npm install -g wrangler
wrangler login

# Create database
wrangler d1 create my-db

# Run SQL
wrangler d1 execute my-db --command "CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT, email TEXT UNIQUE)"
Enter fullscreen mode Exit fullscreen mode

Use in Workers

// src/index.ts
export default {
  async fetch(request: Request, env: Env) {
    const url = new URL(request.url);

    if (url.pathname === "/users" && request.method === "GET") {
      const { results } = await env.DB.prepare(
        "SELECT * FROM users ORDER BY id DESC LIMIT 20"
      ).all();
      return Response.json(results);
    }

    if (url.pathname === "/users" && request.method === "POST") {
      const { name, email } = await request.json();
      const result = await env.DB.prepare(
        "INSERT INTO users (name, email) VALUES (?, ?) RETURNING *"
      ).bind(name, email).first();
      return Response.json(result, { status: 201 });
    }

    if (url.pathname.startsWith("/users/") && request.method === "GET") {
      const id = url.pathname.split("/")[2];
      const user = await env.DB.prepare(
        "SELECT * FROM users WHERE id = ?"
      ).bind(id).first();
      if (!user) return new Response("Not found", { status: 404 });
      return Response.json(user);
    }

    return new Response("Not found", { status: 404 });
  },
};
Enter fullscreen mode Exit fullscreen mode

Configuration

# wrangler.toml
name = "my-api"
main = "src/index.ts"
compatibility_date = "2026-03-01"

[[d1_databases]]
binding = "DB"
database_name = "my-db"
database_id = "xxxxx-xxxx-xxxx"
Enter fullscreen mode Exit fullscreen mode

Batch Operations

const results = await env.DB.batch([
  env.DB.prepare("INSERT INTO users (name, email) VALUES (?, ?)").bind("Alice", "alice@example.com"),
  env.DB.prepare("INSERT INTO users (name, email) VALUES (?, ?)").bind("Bob", "bob@example.com"),
  env.DB.prepare("SELECT count(*) as total FROM users"),
]);
Enter fullscreen mode Exit fullscreen mode

All queries execute in a single transaction — atomic and fast.

Migrations

# Create migration
wrangler d1 migrations create my-db add_posts_table

# Edit migration file
# migrations/0001_add_posts_table.sql:
# CREATE TABLE posts (
#   id INTEGER PRIMARY KEY,
#   title TEXT NOT NULL,
#   content TEXT,
#   author_id INTEGER REFERENCES users(id),
#   created_at DATETIME DEFAULT CURRENT_TIMESTAMP
# );

# Apply
wrangler d1 migrations apply my-db

# Apply to production
wrangler d1 migrations apply my-db --remote
Enter fullscreen mode Exit fullscreen mode

Time Travel (Point-in-Time Recovery)

# Restore to a specific point
wrangler d1 time-travel restore my-db --timestamp 2026-03-28T10:00:00Z

# List bookmarks
wrangler d1 time-travel info my-db
Enter fullscreen mode Exit fullscreen mode

Free 30-day point-in-time recovery. Undo any mistake.

D1 + Hono (Modern API Framework)

import { Hono } from "hono";

type Bindings = { DB: D1Database };
const app = new Hono<{ Bindings: Bindings }>();

app.get("/api/posts", async (c) => {
  const { results } = await c.env.DB.prepare(
    "SELECT p.*, u.name as author FROM posts p JOIN users u ON p.author_id = u.id ORDER BY p.created_at DESC"
  ).all();
  return c.json(results);
});

app.post("/api/posts", async (c) => {
  const { title, content, author_id } = await c.req.json();
  const post = await c.env.DB.prepare(
    "INSERT INTO posts (title, content, author_id) VALUES (?, ?, ?) RETURNING *"
  ).bind(title, content, author_id).first();
  return c.json(post, 201);
});

export default app;
Enter fullscreen mode Exit fullscreen mode

Free Tier

Resource Free Paid
Storage 5 GB 5 GB + $0.75/GB
Reads 5M/day Unlimited ($0.001/M)
Writes 100K/day Unlimited ($1.00/M)
Databases 50 50,000
Time Travel 30 days 30 days

Need edge-first database architecture or Cloudflare Workers setup?

📧 spinov001@gmail.com
🔧 My tools on Apify Store

SQLite at the edge — is D1 the future of serverless databases?

Top comments (0)