Cloudflare Workers + D1を試してみた
個人開発をやっているといつも
「データベース何を使おう」、「どこにホスティングしよう」とかいろいろ悩むのですが
今回は聞いたことあるけど使ったことがなかったCloudeflareのサービスを使ってみようと思いたち、
ついでにやったことを記事にしてみました。
📝 Cloudflareとは?
https://www.cloudflare.com/ja-jp/learning/what-is-cloudflare/
Cloudflareは、Webサイトやアプリを高速かつ安全に配信するためのグローバルネットワークサービスです。
CDN(コンテンツ配信)、DDoS対策、WAF、DNSなどをワンクリックで利用でき、開発者向けにはサーバレス基盤「Workers」やデータベース「D1」も提供しています。
Cloudflare Workers
サーバレス関数です!lambdaみたいなものです!
Cloudflare D1
Cloudflare Workersから利用できるSQLiteベースのサーバレスDBです!
個人的な魅力ポイント
- 時間ではなく読み書きベースの課金
- 無料枠も大きい
- freeアカウントでもDBが10個も作れる
詳しくは公式の料金表を参照ください!
https://developers.cloudflare.com/d1/platform/pricing/
🎯 今回やること
今回はクライアント ↔︎ API (Workers(Hono)) ↔︎ DB (D1)の構成で、
DBに入ってるTodoリストをresponseするだけのAPIを作成したいと思います!
workersで使用するフレームワークはHonoにしました!
💻 環境
$ npm -v
11.4.2
$ node -v
v22.14.0
作業前にCloudeflareのアカウントは事前に作成しました!
⚙️ まずはWorkersを作成する
npm create cloudflare@latest -- worker
いろいろ尋ねられるのですが、以下のように設定しました!
What would you like to start with?
→ ● Framework Starter→● Hono
Do you want to use git for version control?
→ Yes
Do you want to deploy your application?
→ No
念のためnpm run devでapiが立ち上がるのも確認しておきます!

🗄️ D1の作成
次にd1 DBを作成します!
npx wrangler@latest d1 create todo-app
ダッシュボードを確認すると新しくd1 DBが作成されたことがわかります!

以下のコマンドでも確認できます
npx wrangler d1 list
~/projects/todo-d1/worker (main ✔) npx wrangler d1 list
⛅️ wrangler 4.25.0
───────────────────
┌──────────────────────────────────────┬──────────┬──────────────────────────┬────────────┬────────────┬───────────┐
│ uuid │ name │ created_at │ version │ num_tables │ file_size │
├──────────────────────────────────────┼──────────┼──────────────────────────┼────────────┼────────────┼───────────┤
│ 1b421315-7d2e-4fb9-8034-660862e4efcf │ todo-app │ 2025-07-22T10:02:17.238Z │ production │ 0 │ 12288 │
└──────────────────────────────────────┴──────────┴──────────────────────────┴────────────┴────────────┴───────────┘
🔗 WorkerとD1を紐付け
先ほど作ったworkerプロジェクト内にwrangler.jsoncがあるのでこのファイルに
d1_databasesを追記します!
- binding
- worker内からd1を参照するときに使う名前 (javascriptの変数名のルールに従う必要あり!)
- database_name
- 先ほど作ったdatabaseの名前
- database_id
- 先ほど作ったdatabaseのuuid
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "worker",
"main": "src/index.ts",
"compatibility_date": "2025-07-19",
"assets": {
"binding": "ASSETS",
"directory": "./public"
},
"observability": {
"enabled": true
},
+ "d1_databases": [
+ {
+ "binding": "TODO_DB",
+ "database_name": "todo-app",
+ "database_id": "d4704aeb-0299-4396-b71c-6f239bb68db3"
+ }
]
}
migration
マイグレーションファイルを作成します
npx wrangler d1 migrations create <binding名> <好きな名前>
migrationsディレクトリ作っていい?と聞かれるのでyを押します。
~/todo-d1/worker npx wrangler d1 migrations create TODO_DB init
⛅️ wrangler 4.25.0
───────────────────
✔ No migrations folder found. Set `migrations_dir` in your wrangler.json file to choose a different path.
Ok to create /Users/haraguchi/projects/todo-d1/worker/migrations? … yes
✅ Successfully created Migration '0001_init.sql'!
The migration is available for editing here
/Users/haraguchi/projects/todo-d1/worker/migrations/0001_init.sql
migrationsディレクトリの中に0001_init.sqlができていると思います!
ここに作りたいテーブルのSQLを記載します!
今回は以下のようなsqlを書きました!
-- Migration number: 0001 2025-07-19T06:30:04.036Z
-- 古いテーブルがあれば削除
DROP TABLE IF EXISTS Todos;
-- Todo テーブル作成
CREATE TABLE IF NOT EXISTS Todos (
Id INTEGER PRIMARY KEY AUTOINCREMENT,
Title TEXT NOT NULL,
Done INTEGER DEFAULT 0,
CreatedAt TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M:%fZ','now'))
);
-- 初期データの投入
INSERT INTO Todos (Title, Done)
VALUES
('洗濯物を干す', 0),
('エルデンリングをする', 1),
('草むしり', 0);
apply
migrationファイルをローカル用のd1にapplyします!
npx wrangler d1 migrations apply <binding名>
~/todo-d1/worker npx wrangler d1 migrations apply TODO_DB
⛅️ wrangler 4.25.0
───────────────────
Migrations to be applied:
┌───────────────┐
│ name │
├───────────────┤
│ 0001_init.sql │
└───────────────┘
✔ About to apply 1 migration(s)
Your database may not be available to serve requests during the migration, continue? … yes
🌀 Executing on local database TODO_DB (d4704aeb-0299-4396-b71c-6f239bb68db3) from .wrangler/state/v3/d1:
🌀 To execute on your remote database, add a --remote flag to your wrangler command.
🚣 4 commands executed successfully.
┌───────────────┬────────┐
│ name │ status │
├───────────────┼────────┤
│ 0001_init.sql │ ✅ │
└───────────────┴────────┘
applyされてtodosにデータが入っていることを確認します!
executeを使用すると作ったローカルのd1DBに対してSQLを使用できます
~/todo-d1/worker npx wrangler d1 execute TODO_DB --command "SELECT * FROM Todos;"
⛅️ wrangler 4.25.0
───────────────────
🌀 Executing on local database TODO_DB (d4704aeb-0299-4396-b71c-6f239bb68db3) from .wrangler/state/v3/d1:
🌀 To execute on your remote database, add a --remote flag to your wrangler command.
🚣 1 command executed successfully.
┌────┬──────────────────────┬──────┬──────────────────────────┐
│ Id │ Title │ Done │ CreatedAt │
├────┼──────────────────────┼──────┼──────────────────────────┤
│ 1 │ 洗濯物を干す │ 0 │ 2025-07-19T06:49:01.952Z │
├────┼──────────────────────┼──────┼──────────────────────────┤
│ 2 │ エルデンリングをする │ 1 │ 2025-07-19T06:49:01.952Z │
├────┼──────────────────────┼──────┼──────────────────────────┤
│ 3 │ 草むしり │ 0 │ 2025-07-19T06:49:01.952Z │
└────┴──────────────────────┴──────┴──────────────────────────┘
問題なくテーブルが作成できていそうなので次はリモートのd1にapplyします!
applyコマンドに--remoteオプションをつけるだけです!
~/todo-d1/worker npx wrangler d1 migrations apply TODO_DB --remote
⛅️ wrangler 4.25.0
───────────────────
Migrations to be applied:
┌───────────────┐
│ name │
├───────────────┤
│ 0001_init.sql │
└───────────────┘
✔ About to apply 1 migration(s)
Your database may not be available to serve requests during the migration, continue? … yes
🌀 Executing on remote database TODO_DB (d4704aeb-0299-4396-b71c-6f239bb68db3):
🌀 To execute on your local development database, remove the --remote flag from your wrangler command.
🚣 Executed 4 commands in 1.1784ms
┌───────────────┬────────┐
│ name │ status │
├───────────────┼────────┤
│ 0001_init.sql │ ✅ │
└───────────────┴────────┘
webコンソールから確認したところちゃんとテーブルできていることが確認できました!
(マイグレーションテーブルとシーケンステーブルも一緒に作ってくれるみたいです)

🚀 api作る
src/index.tsに以下を貼り付けます!
import { Hono } from "hono";
type Bindings = {
// 設定したbinding名に書き換えてください!
TODO_DB: D1Database
}
type Todo = {
Id: number
Title: string
Done: number
CreatedAt: string
}
const app = new Hono<{ Bindings: Bindings }>();
app.get("/todos", async (c) => {
const { results } = await c.env.TODO_DB
.prepare("SELECT * FROM Todos ORDER BY Id DESC")
.all<Todo>()
return c.json(results)
})
export default app;
開発環境を立ち上げて
npm run dev
curl投げてtodoリストが返ってくればとりあえずOKです!
curl http://localhost:8787/todos
[
{"Id":3,"Title":"草むしり","Done":0,"CreatedAt":"2025-07-19T06:49:01.952Z"},
{"Id":2,"Title":"エルデンリングをする","Done":1,"CreatedAt":"2025-07-19T06:49:01.952Z"},
{"Id":1,"Title":"洗濯物を干す","Done":0,"CreatedAt":"2025-07-19T06:49:01.952Z"}
]
最後にdeployしてapiが使えるか試してみましょう!
npm run deploy
> deploy
> wrangler deploy --minify
⛅️ wrangler 4.25.0
───────────────────
🌀 Building list of assets...
✨ Read 1 file from the assets directory /Users/haraguchi/projects/todo-d1/worker/public
🌀 Starting asset upload...
Total Upload: 20.01 KiB / gzip: 8.11 KiB
Your Worker has access to the following bindings:
Binding Resource
env.TODO_DB (todo-app) D1 Database
env.ASSETS Assets
Uploaded worker (18.95 sec)
Deployed worker triggers (1.23 sec)
https://worker.haraguchi-shoya.workers.dev
Current Version ID: 14888667-709a-404c-a6fd-34c914b6aac7
使えました!
curl https://worker.haraguchi-shoya.workers.dev/todos
[
{"Id":3,"Title":"草むしり","Done":0,"CreatedAt":"2025-07-19T07:20:13.462Z"},
{"Id":2,"Title":"エルデンリングをする","Done":1,"CreatedAt":"2025-07-19T07:20:13.462Z"},
{"Id":1,"Title":"洗濯物を干す","Done":0,"CreatedAt":"2025-07-19T07:20:13.462Z"}
]
🎉 まとめ
今回は、Cloudflare Workers + D1を使って超シンプルなapiを作成しました!
できたこと
- Cloudflare Workers を使ったAPIの実装
- Cloudflare D1でサーバーレスなデータベースを構築
良かった点
- 開発体験が良い: ローカルD1での開発→リモートへのデプロイが簡単!
- コスパが良い: D1は読み書き回数ベースの課金で、無料枠も多い!
- シンプルな構成: Workers + D1の組み合わせで、インフラ管理不要!
Cloudflare D1は無料枠が大きく、読み書き回数ベースの課金体系なので、個人開発や小規模プロジェクトにぴったりです。
そしてサーバーレスで簡単にAPIとDBを構築できるのが魅力的でした!
ぜひ皆さんも試してみてください!
参考リンク
Curious Vehicle では新しい仲間を募集しています!
募集中の職種については弊社のホームページをご覧ください。
https://www.curicle.jp/recruit/
Discussion