はじめに
最近 Cloudflare Workers のデプロイ速度にニヤニヤしてる @guppy0356 です。
Mozilla Pocket が 2025/07/08 に終了してしまい「じゃあ自分専用の保存ツール作るか〜」ってなったのが発端です。
https://support.mozilla.org/en-US/kb/future-of-pocket
今回は Neon + Drizzle + Hono + Cloudflare Workers の “今っぽい全部盛り” で、共有メニューから URL を保存して一覧できるアプリを作りました。
この記事では、実際にやってみて分かった 最高だった点 と やらかした点(というか苦労) を読みやすさ優先でまとめます。
TL;DR(結論)
- Hono + Cloudflare Workers は正解:デプロイ体験が強すぎる
- Neon のブランチ運用は夢があるが、個人開発でも“管理コスト”は発生(Free は 10 branches / project など制限あり)
- テストが一番つらい:Postgres を絡めた並列テストは “設計” が必要になりがち
- もし次やるなら:
- D1(テストやローカル体験の単純さ優先) か
- Postgres継続なら Hyperdrive 等も検討(Workers から Postgres を扱う前提で)
この記事はこんな人向け
- Cloudflare Workers + Hono で API 作りたい
- Neon の「DB ブランチ機能」に夢見てる
- Drizzle ORM で TypeScript 型安全やりたい
- Vitest と RDB の相性で悩みたくない(でも現実どうなのか知りたい)
- D1 と Neon、結局どっちが良いの?で揺れてる
作ったもの(ざっくり)
- 共有メニュー(Share)から URL を保存
- 保存した URL 一覧表示
- OAuth ログイン(Hono の middleware でサクッと)
構成イメージ:
PWA (Web Share Target / UI)
|
| HTTPS fetch
v
Cloudflare Workers
(Hono API + Drizzle ORM [library])
|
| DB driver (HTTP/WebSocket)
v
Neon (PostgreSQL)
期待と現実:Neon 編
期待してたこと
-
compose.yml からの解放
ローカルに DB 立てず、本番DBから一瞬でブランチ作って開発環境にする
→ “最強の開発体験” を期待してました
現実①:ブランチ運用の壁(制限と管理)
Neon のブランチは便利なんだけど、運用が増えると管理コストも増える。
- Free プランは 10 branches / project(2026/01 時点の docs)
https://neon.com/docs/introduction/plans
- PRごとに preview ブランチ作る運用などは、人数やツール連携次第で上限に当たりやすい
- (手動運用だと)どのブランチにどのマイグレーションが適用済みか分からなくなる
ブランチが増えるほど schema の状態把握が難しくなり、「このPRのDBは最新だっけ?」の確認コストが地味に効く
現実②:ローカル開発の再現性(Proxy との付き合い)
Workers から Neon へは HTTP/WebSocket 経由の接続になる。ローカルでも “それっぽく” するため proxy が必要になりがち。
Neon のガイドには、community 製の local-neon-http-proxy を使う手順が載ってます:
- ガイド: https://neon.com/guides/local-development-with-neon
- proxy repo: https://github.com/TimoWilhelm/local-neon-http-proxy
「公式に紹介されてる」=「公式サポートのプロダクト」ではないので、ここが気になる人はいるはず。
(※もちろん動く。動くんだけど、“部品が増える” のがしんどい)
代替の方向性(Neon側)
Neon は Neon Local という “ローカルからNeonに繋ぐための proxy” も用意してるので、気になる人はこっちも見ると良いです。
テストの苦労:Vitest と並列実行の罠
Workers 側のテスト自体は、Cloudflare が Workers Vitest integration を用意してくれてるので、土台はかなり良いです。
- 公式: https://developers.cloudflare.com/workers/testing/vitest-integration/
- Getting started: https://developers.cloudflare.com/workers/testing/vitest-integration/write-your-first-test/
ただし。
つらいポイント:DB が 1つだと、並列テストで衝突する
Vitest はデフォルトで並列実行されるので、同一DBに対してテストデータが衝突します。
Rails みたいに “テストDBを自動で複数割り当て” みたいな仕組みが無いと、工夫が必要。
自分は結局、割り切って 直列実行 に倒しました(個人開発ならアリ)。
// vitest.config.ts(例)
import { defineWorkersConfig } from "@cloudflare/vitest-pool-workers/config";
export default defineWorkersConfig({
test: {
poolOptions: {
workers: {
singleWorker: true,
wrangler: { configPath: "./wrangler.toml" },
},
},
},
});
Cloudflare 側の docs でも singleWorker: true について触れてます:
https://developers.cloudflare.com/workers/testing/vitest-integration/isolation-and-concurrency/
「D1なら楽だった?」について(自分の肌感)
D1(SQLite)だと、Workers のテスト統合と相性が良い印象です。(もちろん別のクセもある)。
一方で Postgres を選ぶと、
- テストの “並列化戦略”(schema分離、db分離、branch分離 等)を考える
- その結果、CIやローカルの構成が重くなる
ここが “Neon にこだわった代償” でした。
余談:PGlite を試したけど、沼った
テストだけ PGlite(Postgres互換のWASM)を使う案も試したんですが、「本番の接続/運用(Neon前提)」と「テスト用の別DB」を両立する設計コストが重くて断念しました。
さらに地味にキツかったのが マイグレーションの適用。
Drizzle の migrator は migrationsFolder(SQLファイルのフォルダ)を読む設計で、内部的に node:fs / node:path などの Node API を前提にしています。なので @cloudflare/vitest-pool-workers(Workers ランタイムでテストを動かすやつ)上だと、ローカルのファイルパスを読んでマイグレーションを当てる…が素直にできず詰みました。
「これなら D1 で良かったのでは…?」の思考が加速しました。
Drizzle ORM:DX は高い。でも罠もある
良かった点
-
Drizzle Kit Studio が最高
ブラウザでレコードをサクサク触れるの、個人開発だと効きます
踏み抜いた点①:UUID 周り
主キー UUID にしたとき、テストデータ投入で Drizzle 側の挙動にハマった話を別で書いてます:
踏み抜いた点②:ロールバックが標準で強くない
「migrate down が欲しい」系は昔から議論があり、現状(少なくとも多くの人の認識として)は 手動運用が混ざりやすい です。
- Discussion: https://github.com/drizzle-team/drizzle-orm/discussions/1339
- Feature issue: https://github.com/drizzle-team/drizzle-orm/issues/2352
Hono + Cloudflare Workers:ここは「正解」だった
ここは文句なしに良かった。
-
GitHub 連携で main push → 自動デプロイ
“デプロイが早い” ってだけで開発の気持ちよさが変わる -
ミドルウェアが揃って OAuth もサクッと
認証周りの “重さ” が少ないのは正義
運用のハック:ビルド時マイグレーション(※個人開発の割り切り)
GitHub Actions を作り込むのが面倒で、Cloudflare の Build command にこれ入れてます。
npm run db:migrate && npm run build
正直荒いけど、個人開発なら “回る”。
注意(真似するならここだけ読んで)
- 同時デプロイが走ると migration 競合しうる
- “ビルドがDBを書き換える” ので、責務分離的に好みが分かれる
- 失敗時にデプロイが止まる
なので、チーム開発/商用なら普通に CI で migration を管理した方が安全。
まとめ:次の一手どうする?
結論としてはこれ。
「Hono + Cloudflare Workers は最高。でも DB は D1 の方が“リスク低い”場面が多かったかも」
自分の中での “リスク” は主にこれ:
- テストが書きやすい(= 継続できる)
- ローカル開発の構成が単純(= 未来の自分が壊さない)
- 運用の部品が少ない(= 詰みにくい)
ただ、Postgres を続けるなら Cloudflare の Hyperdrive も選択肢に入れる価値があると思ってます(Workers → Postgres 接続の前提で設計されてるやつ)。
- Get started: https://developers.cloudflare.com/hyperdrive/get-started/
- Connect to Postgres: https://developers.cloudflare.com/hyperdrive/examples/connect-to-postgres/
- Connection pooling: https://developers.cloudflare.com/hyperdrive/concepts/connection-pooling/
動作確認済み環境
- macOS / Apple Silicon
- Node.js v20.x
- Hono
- Drizzle ORM
- Neon (PostgreSQL 15)
- Cloudflare Workers
参考リンク(一次情報)
- Pocket 終了(Mozilla公式): https://support.mozilla.org/en-US/kb/future-of-pocket
- Neon plans(branch制限含む): https://neon.com/docs/introduction/plans
- Neon ローカル開発ガイド(local-neon-http-proxy言及): https://neon.com/guides/local-development-with-neon
- local-neon-http-proxy: https://github.com/TimoWilhelm/local-neon-http-proxy
- Neon Local: https://neon.com/docs/local/neon-local
- Workers Vitest integration: https://developers.cloudflare.com/workers/testing/vitest-integration/
- Isolation and concurrency(singleWorker言及): https://developers.cloudflare.com/workers/testing/vitest-integration/isolation-and-concurrency/
- Drizzle rollback 議論: https://github.com/drizzle-team/drizzle-orm/discussions/1339
- Drizzle rollback feature issue: https://github.com/drizzle-team/drizzle-orm/issues/2352