sellStorage & Databases
database

D1

A real SQL database you can spin up in seconds — no servers to run.

5MFree rows read / day
100KFree rows written / day
5 GBFree storage
30 daysTime Travel recovery
lightbulb

What is D1?

D1 is a serverless SQL database (SQL = the standard language for storing data in tables of rows and columns; serverless = you never set up or manage a database server yourself). It runs on SQLite, a tiny, rock-solid database engine used in billions of devices.

You define tables, write familiar SQL queries (SELECT, INSERT, UPDATE), and D1 handles the storage, backups, and scaling for you. It is designed to work hand-in-hand with Cloudflare Workers.

table_chart

Think of it like…

A super-powered spreadsheet that lives in the cloud. Each table is a sheet with named columns, every row is one record, and SQL is how you ask precise questions like 'show me all customers in Taipei'.

help

Why use D1?

Running your own database means provisioning servers, patching them, and paying even when idle. D1 removes all of that and bills only for the queries and storage you actually use.

toll

Pay per query

No idle server costs — you pay for rows read/written and storage, nothing else.

library_add

Thousands of databases

Create a separate database per customer or project at no extra base cost.

history

Time Travel backups

Restore your database to any point in the last 30 days if something goes wrong.

code

Standard SQL

If you know SQLite or basic SQL, you already know how to use D1.

target

When should you use it?

checklist

App data with relations

Users, posts, orders — data where rows relate to each other and you query with SQL.

person

Per-tenant databases

Give each customer their own isolated database for clean separation.

rocket

Side projects & MVPs

The generous free tier makes it ideal for prototypes and small apps.

hub

Full-stack on Workers

Pair D1 with Workers so your API and database live in the same platform.

rocket_launch

How do you start?

These steps create a database, define a table, run a query from the terminal, and read it from a Worker. The --remote flag means 'run against the real cloud database' (leave it off to test locally).

  1. Create a database

    Wrangler prints a database_id — copy it for the next step.

    bash
    npx wrangler d1 create my-app-db
  2. Bind the database

    Add this to wrangler.jsonc so your Worker can reach it as env.DB.

    json
    {
      "d1_databases": [
        {
          "binding": "DB",
          "database_name": "my-app-db",
          "database_id": "<paste-your-id-here>"
        }
      ]
    }
  3. Create a table & add data

    Run SQL straight from the terminal with --command.

    bash
    npx wrangler d1 execute my-app-db --remote \
      --command "CREATE TABLE customers (id INTEGER PRIMARY KEY, name TEXT, city TEXT);"
    
    npx wrangler d1 execute my-app-db --remote \
      --command "INSERT INTO customers (name, city) VALUES ('Mei', 'Taipei');"
  4. Query from a Worker

    prepare() builds a safe query, bind() fills in the ? placeholder (this prevents SQL injection), and all() returns the rows.

    js
    export default {
      async fetch(request, env) {
        const { results } = await env.DB
          .prepare("SELECT * FROM customers WHERE city = ?")
          .bind("Taipei")
          .all();
        return Response.json(results);
      },
    };
  5. Deploy

    Publish the Worker and your database-backed API is live.

    bash
    npx wrangler deploy
school

Key concepts

grid_on

Table, row, column

A table holds rows (records); each column is a named field like name or city.

shield

Prepared statements

Using prepare() + bind() keeps user input out of the SQL text, blocking injection attacks.

cloud_sync

Local vs remote

Without --remote you query a local copy for fast testing; with it you hit the real cloud database.

restore

Time Travel

D1 keeps history so you can roll back to any moment in the past 30 days.

tips_and_updates

Tips & pricing

payments

Billed by rows, not time

D1 counts rows read and rows written, plus storage. The free tier gives 5 million rows read and 100,000 rows written per day, and 5 GB of storage.

  • Add indexes on columns you filter by often to read fewer rows (and save money).
  • Keep schema changes in a schema.sql file and apply with --file=./schema.sql.
  • Paid plan includes 25 billion rows read and 50 million rows written per month before extra charges.
  • Use D1 for relational data; use KV for simple key lookups and R2 for large files.