PlanetScaleを使用する時の注意点
4分目次
PlanetScale という激アツのサービスが話題となっていた。
何がアツいかというか
- 無料枠がでかい DB(MySQL)サーバー
- 多少膨らんでも 3000 円/月程度(料金表)と低コスト
- 日本リージョンがある
- DB にブランチ機能がある
- コンソールもバックアップもある
ちょっと前は個人開発者がなるべくランニングコストを抑えてサービスを作るとなると heroku を Postgres だけ使用するなどが有効な選択肢だったが、heroku はしょっちゅう sleep してしまう。また、無料枠だとリージョンが限られていたので日本では使用できなかった。
その点、この PlanetScale は日本リージョンがあって無料枠がでかいだけでも相当アツい上になんか Git 的なブランチという概念があって面白い。dev/stg/prd 環境ごとの DB を用意したり、スキーマ情報のマージもできる。
もはや
- Next.js
- Next.js APIroutes
- Vercel
- Prisma
- PlanetScale
で無料かつ簡単な WebAPP を作るためのフルスタック環境が整ったと言っても過言じゃなさそう。
もう見づらいドキュメントを頑張って読んで AWS でインフラ構築する必要がなくなった。
ただし、使ってるとちょっと癖があるというか詰まるとこもあった。
Next.js と使うとリージョン問題が発生する
Next.js というか Vercel はデフォだとエッジサーバーが日本にもあるけど本体はアメリカだかなので、一見速そうでも、PlanetScale を日本で設定するとデータのフェッチに関してが若干遅くなる。
これを解消するには、
- Vercel に 2000 円/月のお布施を払って、日本に置いてもらう
- PlanetScale を Next.js と同じくアメリカに置く
などの対策が必要。
Prisma との併用に癖が強い
Prisma は JS の人なら絶対使ってみるべき ORM で、単純に使いやすい&スキーマを定義するだけで TS の型も生成してくれる。最近本業の方で OpenAPI で数万行にもなり得る yml をシコシコ書いて型生成をしてるので Prisma を使うたびに愛情が溢れる。
ただ、PlanetScale と併用すると若干問題があった。
外部キー禁止
PlanetScale は外部キーを禁止している。Prisma でスキーマを書くときに外部キーが使えない。
ただし、Prisma3.1.1 以降からはプレビュー機能ではあるがそこら辺をよしなにやってくれるreferentialIntegrity
というものがあるらしい。
generator client {
provider = "prisma-client-js"
previewFeatures = ["referentialIntegrity"] // 追加
}
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
referentialIntegrity = "prisma" // 追加
}
これを追加すれば PlanetScale に向けたprisma db push
も可能。(追加しなければエラー)
参考: Using Prisma with a PlanetScale database #7292
migrate 禁止
Prisma で main ブランチに向けて migrate しようとするとエラーがでる。
まず dev/stg など main 以外のブランチに向けて migrate を行い、それらの変更を main に取り込むときは stg => main にマージ(デプロイ)するような流れで行う。
shadow database 問題
Prisma はシャドー DB という擬似 DB 的な謎の力を内部的に使用しており、これが問題で DB との通信が一筋縄ではいかない。ローカル環境で試すときは Docker で MySQL 環境用意して stg/prd では PlanetScale を使うのが手っ取り早いと思っていたが、今確認してみると PlanetScale に shadow db ブランチを用意して Prisma が shadow DB を使用したがったらそちらのブランチを使うなんて方法もあるらしい。
datasource db {
provider = "mysql"
url = env("DATABASE_URL")
shadowDatabaseUrl = env("SHADOW_DATABASE_URL") // 追加
referentialIntegrity = "prisma"
}