Cloudflare D1 Gem

CI Gem Version

Ruby adapters for Cloudflare D1 - SQLite at the edge.

Provides both ActiveRecord and Sequel adapters to use D1 databases from Ruby applications.

Features

  • ActiveRecord adapter - Full Rails integration with migrations
  • Sequel adapter - Lightweight ORM for non-Rails apps
  • Database management - Rake tasks for creating/dropping databases
  • Local development - Use local SQLite for dev, D1 for production
  • Cloudflare Containers - Example Roda app deployable to Cloudflare

Installation

Add to your Gemfile:

gem "cloudflare-d1"

Then run:

bundle install

Or install directly:

gem install cloudflare-d1

Usage

ActiveRecord (Rails)

Configure in config/database.yml:

production:
  adapter: cloudflare_d1
  account_id: <%= ENV['CLOUDFLARE_ACCOUNT_ID'] %>
  api_token: <%= ENV['CLOUDFLARE_API_TOKEN'] %>
  database_id: <%= ENV['DATABASE_ID'] %>

Use standard ActiveRecord:

class User < ActiveRecord::Base
end

# CRUD operations
user = User.create(name: "Alice", email: "[email protected]")
User.where(email: "[email protected]").first
user.update(name: "Alice Smith")
user.destroy

Run migrations:

rake db:create      # Create D1 database
rake db:migrate     # Run migrations
rake db:rollback    # Rollback migrations

Sequel (Non-Rails)

Connect to D1:

require "sequel"
require "sequel/adapters/cloudflare_d1"

DB = Sequel.connect(
  adapter: :cloudflare_d1,
  account_id: ENV["CLOUDFLARE_ACCOUNT_ID"],
  api_token: ENV["CLOUDFLARE_API_TOKEN"],
  database: ENV["DATABASE_ID"]
)

# Use Sequel
DB[:users].insert(name: "Bob", email: "[email protected]")
DB[:users].where(email: "[email protected]").all
DB[:users].where(id: 1).update(name: "Robert")
DB[:users].where(id: 1).delete

Run migrations:

rake sequel:db:migrate

Local Development

For local development, use SQLite directly instead of making API calls:

# config/database.yml
development:
  adapter: sqlite3
  database: db/development.sqlite3

production:
  adapter: cloudflare_d1
  account_id: <%= ENV['CLOUDFLARE_ACCOUNT_ID'] %>
  api_token: <%= ENV['CLOUDFLARE_API_TOKEN'] %>
  database_id: <%= ENV['DATABASE_ID'] %>

Or for Sequel:

if ENV["RACK_ENV"] == "production"
  DB = Sequel.connect(adapter: :cloudflare_d1, ...)
else
  DB = Sequel.connect("sqlite://db/development.db")
end

Examples

Roda + Cloudflare Containers

See the complete example in examples/roda/:

cd examples/roda
./setup.sh  # Automated setup and deployment

Features:

  • Full CRUD API
  • Automatic migrations
  • Deployable to Cloudflare Containers
  • Local development with SQLite

Configuration

Environment Variables

Set these environment variables:

export CLOUDFLARE_ACCOUNT_ID=your_account_id
export CLOUDFLARE_API_TOKEN=your_api_token
export DATABASE_ID=your_database_uuid

Get your credentials:

  • Account ID: wrangler whoami or Cloudflare dashboard
  • API Token: Dashboard → My Profile → API Tokens
    • Create token with "Edit Cloudflare Workers" template
    • Include D1 Database permissions
  • Database ID: wrangler d1 create my-database

Creating a D1 Database

Using Wrangler:

wrangler d1 create my-database

Or using the gem:

# ActiveRecord
rake db:create

# Sequel
DATABASE_NAME=my-database rake sequel:db:create

Rake Tasks

ActiveRecord

rake db:create              # Create D1 database
rake db:drop                # Drop D1 database
rake db:list                # List all D1 databases
rake db:migrate             # Run migrations
rake db:rollback            # Rollback migrations
rake db:migrate_status      # Show migration status
rake db:reset               # Drop, create, migrate
rake db:setup               # Create and migrate

Sequel

rake sequel:db:create       # Create D1 database
rake sequel:db:drop         # Drop D1 database
rake sequel:db:list         # List all D1 databases
rake sequel:db:migrate      # Run migrations
rake sequel:db:rollback     # Rollback migrations
rake sequel:db:status       # Show migration status
rake sequel:db:reset        # Drop, create, migrate
rake sequel:db:setup        # Create and migrate

Limitations

Due to D1's architecture:

  • No DDL transactions - Schema changes aren't wrapped in transactions
  • No savepoints - Transaction savepoints not supported
  • No connection pooling - Each query is an HTTP request
  • API-only access - D1 is not directly accessible outside Cloudflare

These are D1 limitations, not gem limitations.

Development

After checking out the repo:

bundle install
rake test

To install this gem onto your local machine:

bundle exec rake install

Contributing

Bug reports and pull requests are welcome on GitHub.

Releasing

See RELEASING.md for release instructions.

License

The gem is available as open source under the terms of the MIT License.