Skip to content

D1 Database Fundamentals

Before diving into migrations, let’s understand the database we’re working with. Cloudflare D1 is a serverless SQLite database that runs at the edge, and knowing its architecture helps you make better decisions throughout your project.

What is D1?

Cloudflare D1 is a serverless, edge-native SQL database built on SQLite. It’s designed to work seamlessly with Cloudflare Workers, providing low-latency data access from anywhere in the world.

Key Characteristics

  • SQLite-based: D1 uses SQLite under the hood, giving you a familiar SQL dialect with a proven track record
  • Serverless: No database servers to manage, scale, or maintain
  • Edge-native: Your database runs close to your users, reducing latency
  • Zero cold starts: D1 is always ready to serve requests
  • Integrated with Workers: Native binding to Cloudflare Workers with zero configuration

When to Use D1

D1 is an excellent choice when you need:

  • Low-latency reads for global applications
  • Simple, relational data that fits the SQLite model
  • Serverless architecture without managing database infrastructure
  • Cost-effective storage for small to medium datasets
  • Tight integration with Cloudflare Workers

D1 might not be the best fit for:

  • Applications requiring real-time synchronization between multiple writers
  • Very large datasets (hundreds of GB)
  • Complex transactions spanning multiple databases
  • Applications needing specialized database features (full-text search, geospatial queries)

D1 Architecture

Understanding how D1 works helps you design better applications:

flowchart TB
  subgraph UserRequest["User Request"]
      User["User (Global)"]
  end

  subgraph CloudflareNetwork["Cloudflare Global Network"]
      Edge1["Edge Location 1"]
      Edge2["Edge Location 2"]
      Edge3["Edge Location 3"]

      subgraph Worker["Cloudflare Worker"]
          API["Your API Code"]
          D1Binding["D1 Binding"]
      end

      subgraph D1Database["D1 Database"]
          Primary["Primary<br/>(Writes)"]
          Replica1["Read Replica"]
          Replica2["Read Replica"]
      end
  end

  User --> Edge1
  User --> Edge2
  User --> Edge3

  Edge1 --> Worker
  Edge2 --> Worker
  Edge3 --> Worker

  API --> D1Binding
  D1Binding --> Primary
  D1Binding --> Replica1
  D1Binding --> Replica2

  Primary -.->|"Replication"| Replica1
  Primary -.->|"Replication"| Replica2

How D1 Handles Requests

  1. User requests arrive at the nearest Cloudflare edge location
  2. Workers execute your API code at the edge
  3. D1 bindings route queries to the optimal database location
  4. Read replicas serve read queries from nearby locations
  5. Primary database handles all write operations

This architecture means reads are fast (served from nearby replicas), while writes go to a central primary location to maintain consistency.

Local vs Remote D1

When developing with D1, you work with two different database environments:

Local D1 (Development)

During development, Wrangler creates a local SQLite database on your machine:

Terminal window
# Start local development server with local D1
pnpm dev

Local D1 characteristics:

AspectBehavior
Location.wrangler/state/v3/d1/ directory
PerformanceInstant queries (no network)
Data persistenceSurvives restarts, reset with reset:* scripts
MigrationsApplied with wrangler d1 migrations apply --local

Remote D1 (Staging/Production)

In staging and production, your database runs on Cloudflare’s infrastructure:

Terminal window
# Apply migrations to remote database
wrangler d1 migrations apply YOUR_DATABASE_NAME --remote

Remote D1 characteristics:

AspectBehavior
LocationCloudflare’s global network
PerformanceDepends on user proximity to replicas
Data persistenceHighly durable, replicated storage
MigrationsApplied with --remote flag

Environment Parity

To avoid surprises in production, keep your environments aligned:

  1. Use the same schema across local and remote databases
  2. Test migrations locally before applying to remote
  3. Use similar data volumes when performance testing
  4. Run integration tests against local D1 before deploying

D1 Limitations

Understanding D1’s constraints helps you design appropriate solutions:

Size Limits

ResourceLimit
Database size10 GB per database
Row size1 MB maximum
SQL query size100 KB maximum
Bound parameters100 per query

Performance Considerations

AspectConsideration
Write latencyHigher than reads (goes to primary)
Concurrent writesSingle-writer model (serialized)
Complex queriesMay be slower than dedicated databases
JoinsEfficient for small-to-medium tables

SQLite Compatibility

D1 supports most SQLite features with some exceptions:

Supported:

  • Standard SQL queries (SELECT, INSERT, UPDATE, DELETE)
  • Transactions and ACID compliance
  • Indexes and constraints
  • Common table expressions (CTEs)
  • JSON functions
  • Window functions

Not supported or limited:

  • ATTACH DATABASE (single database per binding)
  • User-defined functions (UDFs)
  • Full-text search (FTS5) — currently in beta
  • R-Tree spatial indexes
  • Some PRAGMA statements

D1 Strengths

D1 offers compelling advantages for the right use cases:

Developer Experience

  • Familiar SQL: If you know SQL, you know D1
  • Local development: Full-featured local database with Wrangler
  • Type safety: Excellent ORM support (Drizzle, Prisma)
  • Zero configuration: Bindings just work with Workers

Operational Benefits

  • No infrastructure: Cloudflare manages everything
  • Automatic backups: Point-in-time recovery available
  • Global distribution: Read replicas worldwide
  • Cost-effective: Pay only for what you use

Performance Characteristics

OperationPerformance
Simple readsSub-10ms from edge
Complex queriesDepends on data size and query complexity
WritesConsistent latency to primary
TransactionsACID-compliant with serializable isolation

Integration Benefits

  • Native Workers binding: No connection strings or pools
  • Environment-aware: Automatic local/remote switching
  • Migration-friendly: Works well with Drizzle Kit
  • Wrangler CLI: Comprehensive tooling included

When D1 Shines

D1 is particularly well-suited for these scenarios:

  1. Content-driven sites: Blogs, documentation, marketing sites
  2. User-generated content: Comments, reviews, posts
  3. Configuration storage: Feature flags, settings, preferences
  4. Session management: User sessions, authentication data
  5. API backends: REST/GraphQL APIs with moderate traffic
  6. Multi-tenant apps: Isolated databases per tenant

Summary

D1 is a powerful choice for serverless applications that need:

  • Global, low-latency data access
  • Familiar SQL-based development
  • Zero infrastructure management
  • Tight Cloudflare Workers integration

Understanding these fundamentals prepares you for the next step: learning how Drizzle ORM makes working with D1 even better.