Skip to content

Get started

Last reviewed: 17 days ago

This guide instructs you through:

  • Creating your first database using D1, Cloudflare’s native serverless SQL database.
  • Creating a schema and querying your database via the command-line.
  • Connecting a Cloudflare Worker to your D1 database to query your D1 database programmatically.

Prerequisites

To continue:

  1. Sign up for a Cloudflare account if you have not already.
  2. Install npm.
  3. Install Node.js. Use a Node version manager like Volta or nvm to avoid permission issues and change Node.js versions. Wrangler requires a Node version of 16.17.0 or later.

1. Create a Worker

Create a new Worker as the means to query your database.

  1. Create a new project named d1-tutorial by running:

    Terminal window
    npm create cloudflare@latest -- d1-tutorial

    For setup, select the following options:

    • For What would you like to start with?, choose Hello World example.
    • For Which template would you like to use?, choose Hello World Worker.
    • For Which language do you want to use?, choose TypeScript.
    • For Do you want to use git for version control?, choose Yes.
    • For Do you want to deploy your application?, choose No (we will be making some changes before deploying).

    This creates a new d1-tutorial directory as illustrated below.

    • Directoryd1-tutorial
      • Directorynode_modules/
      • Directorytest/
      • Directorysrc
        • index.ts
      • package-lock.json
      • package.json
      • testconfig.json
      • vitest.config.mts
      • worker-configuration.d.ts
      • wrangler.toml

    Your new d1-tutorial directory includes:

    • A "Hello World" Worker in index.ts.
    • A wrangler.toml configuration file. wrangler.toml is how your d1-tutorial Worker accesses your D1 database.

2. Create a database

A D1 database is conceptually similar to many other databases: a database may contain one or more tables, the ability to query those tables, and optional indexes. D1 uses the familiar SQL query language (as used by SQLite).

To create your first D1 database:

  1. Change into the directory you just created for your Workers project:

    Terminal window
    cd d1-tutorial
  2. Run the following wrangler d1 command and give your database a name. In this tutorial, the database is named prod-d1-tutorial:

    Terminal window
    npx wrangler d1 create prod-d1-tutorial
    Successfully created DB 'prod-d1-tutorial'
    [[d1_databases]]
    binding = "DB" # available in your Worker on env.DB
    database_name = "prod-d1-tutorial"
    database_id = "<unique-ID-for-your-database>"

This creates a new D1 database and outputs the binding configuration needed in the next step.

3. Bind your Worker to your D1 database

You must create a binding for your Worker to connect to your D1 database. Bindings allow your Workers to access resources, like D1, on the Cloudflare developer platform. You create bindings by updating your wrangler.toml file.

To bind your D1 database to your Worker:

  1. Copy the lines obtained from step 2 from your terminal.

  2. Add them to the end of your wrangler.toml file.

    [[d1_databases]]
    binding = "DB" # available in your Worker on env.DB
    database_name = "prod-d1-tutorial"
    database_id = "<unique-ID-for-your-database>"

    Specifically:

    • The value (string) you set for binding is the binding name, and is used to reference this database in your Worker. In this tutorial, name your binding DB.
    • The binding name must be a valid JavaScript variable name. For example, binding = "MY_DB" or binding = "productionDB" would both be valid names for the binding.
    • Your binding is available in your Worker at env.<BINDING_NAME> and the D1 client API is exposed on this binding.

You can also bind your D1 database to a Pages Function. For more information, refer to Functions Bindings for D1.

4. Run a query against your D1 database

Configure your D1 database

With wrangler.toml configured properly, set up your database. Use the example schema.sql file below to initialize your database.

  1. Copy the following code and save it as a schema.sql file in the d1-tutorial Worker directory you created in step 1:

    DROP TABLE IF EXISTS Customers;
    CREATE TABLE IF NOT EXISTS Customers (CustomerId INTEGER PRIMARY KEY, CompanyName TEXT, ContactName TEXT);
    INSERT INTO Customers (CustomerID, CompanyName, ContactName) VALUES (1, 'Alfreds Futterkiste', 'Maria Anders'), (4, 'Around the Horn', 'Thomas Hardy'), (11, 'Bs Beverages', 'Victoria Ashworth'), (13, 'Bs Beverages', 'Random Name');
  2. Initialize your database to run and test locally first. Bootstrap your new D1 database by running:

    Terminal window
    npx wrangler d1 execute prod-d1-tutorial --local --file=./schema.sql
  3. Validate your data is in your database by running:

    Terminal window
    npx wrangler d1 execute prod-d1-tutorial --local --command="SELECT * FROM Customers"
    🌀 Mapping SQL input into an array of statements
    🌀 Executing on local database production-db-backend (5f092302-3fbd-4247-a873-bf1afc5150b) from .wrangler/state/v3/d1:
    ┌────────────┬─────────────────────┬───────────────────┐
    CustomerId CompanyName ContactName
    ├────────────┼─────────────────────┼───────────────────┤
    1 Alfreds Futterkiste Maria Anders
    ├────────────┼─────────────────────┼───────────────────┤
    4 Around the Horn Thomas Hardy
    ├────────────┼─────────────────────┼───────────────────┤
    11 Bs Beverages Victoria Ashworth
    ├────────────┼─────────────────────┼───────────────────┤
    13 Bs Beverages Random Name
    └────────────┴─────────────────────┴───────────────────┘

Write queries within your Worker

After you have set up your database, run an SQL query from within your Worker.

  1. Navigate to your d1-tutorial Worker and open the index.ts file. The index.ts file is where you configure your Worker’s interactions with D1.

  2. Clear the content of index.ts.

  3. Paste the following code snippet into your index.ts file:

    export interface Env {
    // If you set another name in wrangler.toml as the value for 'binding',
    // replace "DB" with the variable name you defined.
    DB: D1Database;
    }
    export default {
    async fetch(request, env): Promise<Response> {
    const { pathname } = new URL(request.url);
    if (pathname === "/api/beverages") {
    // If you did not use `DB` as your binding name, change it here
    const { results } = await env.DB.prepare(
    "SELECT * FROM Customers WHERE CompanyName = ?",
    )
    .bind("Bs Beverages")
    .all();
    return Response.json(results);
    }
    return new Response(
    "Call /api/beverages to see everyone who works at Bs Beverages",
    );
    },
    } satisfies ExportedHandler<Env>;

    In the code above, you:

    1. Define a binding to your D1 database in your TypeScript code. This binding matches the binding value you set in wrangler.toml under [[d1_databases]].
    2. Query your database using env.DB.prepare to issue a prepared query with a placeholder (the ? in the query).
    3. Call bind() to safely and securely bind a value to that placeholder. In a real application, you would allow a user to define the CompanyName they want to list results for. Using bind() prevents users from executing arbitrary SQL (known as “SQL injection”) against your application and deleting or otherwise modifying your database.
    4. Execute the query by calling all() to return all rows (or none, if the query returns none).
    5. Return your query results, if any, in JSON format with Response.json(results).

After configuring your Worker, you can test your project locally before you deploy globally.

5. Develop locally with Wrangler

While in your project directory, test your database locally.

  1. Run wrangler dev:

    Terminal window
    npx wrangler dev

    When you run wrangler dev, Wrangler provides a URL (most likely localhost:8787) to review your Worker.

  2. Navigate to the URL.

    The page displays Call /api/beverages to see everyone who works at Bs Beverages.

  3. Test your database is running successfully. Add /api/beverages to the provided Wrangler URL. For example, localhost:8787/api/beverages.

If successful, the browser displays your data.

6. Deploy your database

To deploy your Worker to production, you must first repeat the database bootstrapping steps after replacing the --local flag with the --remote flag to give your Worker data to read. This creates the database tables and imports the data into the production version of your database, running on Cloudflare’s global network.

  1. Bootstrap your database with the schema.sql file you created in step 4:

    Terminal window
    npx wrangler d1 execute prod-d1-tutorial --remote --file=./schema.sql
  2. Validate the data is in production by running:

    Terminal window
    npx wrangler d1 execute prod-d1-tutorial --remote --command="SELECT * FROM Customers"
  3. Deploy your Worker to make your project accessible on the Internet. Run:

    Terminal window
    npx wrangler deploy
    Outputs: https://d1-tutorial.<YOUR_SUBDOMAIN>.workers.dev

You can now visit the URL for your newly created project to query your live database.

For example, if the URL of your new Worker is d1-tutorial.<YOUR_SUBDOMAIN>.workers.dev, accessing https://d1-tutorial.<YOUR_SUBDOMAIN>.workers.dev/api/beverages sends a request to your Worker that queries your live database directly.

7. (Optional) Delete your database

To delete your database, run:

Terminal window
npx wrangler d1 delete prod-d1-tutorial

If you want to delete your Worker, run:

Terminal window
npx wrangler delete d1-tutorial

Summary

In this tutorial, you have:

  • Created a D1 database
  • Created a Worker to access that database
  • Deployed your project globally

Next steps

If you have any feature requests or notice any bugs, share your feedback directly with the Cloudflare team by joining the Cloudflare Developers community on Discord.