はじめに
小規模な試合記録アプリを作る中で、DB 基盤として Turso + libSQL を採用しました。
開発環境は Windows です。Turso CLI を使う方法として、WSL 経由であれば Windows でも動きます。
ただ、当時 WSL を使ったことがなく、学習コストを考えると別の方法で進めた方が速いと判断しました。
結論として、WSL なし・Turso CLI なしでも migration 運用は十分回せます。
- DB 作成や token 発行は Turso Web コンソール
- アプリテーブルの schema 管理は手書き SQL ファイル
- migration 適用は
@libsql/clientベースの自前スクリプト - 認証テーブルは Better Auth CLI migrate
WSL に慣れている場合は Turso CLI を使う方が標準的です。この記事は「WSL の学習コストを避けてとにかく進めたい」という状況向けの実践メモです。
今回のDB構成
レイヤー | 技術 |
|---|---|
DB | Turso / libSQL |
Auth | Better Auth |
Hosting | Cloudflare Pages |
Migration適用 | @libsql/client スクリプト / Better Auth CLI |
アプリ本体のテーブル: members, competitions, matches, appearances
認証テーブル(Better Auth導入後): user, session, account, verification
スキーマ定義は src/lib/schema.sql を正本とし、差分は src/lib/migrations/*.sql として管理しています。
migrationの役割とは何か
schema.sql は「最終的にこういうDB構造でありたい」という現在形の定義です。
一方で migration は、「既存のDBをその構造にどうやって追いつかせるか」という履歴です。
この2つは役割が違います。
schema.sql の役割
- アプリが期待している現在のDB構造を表す
- 開発者が今の設計を読むための中心になる
migrations/*.sql の役割
- DBへ順番に適用する差分の履歴になる
- 新しい環境を同じ構造で再現できる
- どのタイミングで何を追加したかを追跡できる
今回は migration が次のように分かれました。
0000_initial.sql— アプリ本体テーブルを作成0001_better_auth.sql— Better Auth 用テーブルを追加
テーブル種別ごとのmigration適用方法
アプリテーブル: @libsql/client スクリプト
アプリ独自テーブルは scripts/migrate-app-tables.mjs で適用します。
import { createClient } from '@libsql/client';
import { readFileSync } from 'fs';
const client = createClient({
url: process.env.TURSO_DATABASE_URL,
authToken: process.env.TURSO_AUTH_TOKEN,
});
const sql = readFileSync('./src/lib/migrations/0000_initial.sql', 'utf-8');
await client.executeMultiple(sql);適用後は scripts/check-schema.mjs でテーブルの作成を確認できます。
const result = await client.execute(
"SELECT name FROM sqlite_master WHERE type='table'"
);
console.log(result.rows);認証テーブル: Better Auth CLI migrate
Better Auth のテーブルは次のコマンドで適用します。手書き SQL を書く必要はありません。
npx better-auth migrateWindows環境でTurso CLIを使わずに進めた理由
Turso CLI は WSL 経由であれば Windows でも動きます。
ただ WSL に慣れていない場合、環境構築自体に時間がかかりがちです。
今回は WSL の学習コストを避けて、Node から直接 Turso に接続する方法を選びました。
アプリとして必要なのは最終的に TURSO_DATABASE_URL と TURSO_AUTH_TOKEN の2つです。これがあれば @libsql/client で直接接続できます。
実際にやったことは次の流れです。
- Turso Web コンソールで開発DB を作成
- Web コンソールで token を発行
.dev.varsに URL と token を保存@libsql/clientで DB に接続- migration SQL を順番に実行
check-schema.mjsでテーブル作成を確認
開発環境での運用
開発環境でやったこと
- 開発DBを本番と分離して作成
.dev.varsに開発用の URL と token を保存- schema 変更後に
migrations/*.sqlを追加 - ローカルから
migrate-app-tables.mjsを実行して適用 - Better Auth テーブルは
npx better-auth migrateで適用 - その後にアプリ動作確認
この運用のメリット
- Windows 環境でも詰まりにくい
- Web コンソールを毎回開かずに進められる
- UI 実装と schema 変更を小刻みに検証できる
- 開発DBなら壊しても復旧しやすい
開発DBは壊しても影響範囲が限定されます。逆に言えば、本番DBは同じ感覚では扱えません。
本番環境で同じ運用をそのまま使わない理由
問題になるのは「高権限 token をどこに置いて、誰が、どの環境に向けて SQL を流せるのか」です。本番環境でローカルから直接 SQL を流す運用は次のリスクがあります。
- 本番 token が開発マシンに置かれる
- 誤って本番DBへ向けて SQL を流す
- schema 変更がレビューなしで反映される
- 開発DBと本番DBの境界が運用で曖昧になる
本番環境での推奨運用
secret の置き場所を分ける
- 開発用:
.dev.vars - 本番用: Cloudflare Pages の secrets など
migration の適用タイミングを分ける
schema.sqlを変更migrations/*.sqlに差分ファイルを追加- 開発DBに先に適用して動作確認
- レビュー後に本番DBへ適用
今回の構成でよかった点
認証を後回しにして先に DB 基盤を作りました。この順序はかなりやりやすかったです。
- 先にドメインテーブルを固められた
- Better Auth 導入時に migration を1本追加するだけで済んだ
- admin 保護の実装時に、どの auth テーブルが必要かが明確だった
まとめ
Windows 環境でも、Turso CLI が前提でなくても DB 開発は十分回せます。
migrations/*.sqlは「DBを順番に更新する履歴」schema.sqlは「今あるべき構造」- アプリテーブルは
@libsql/clientスクリプトで適用できる - 認証テーブルは Better Auth CLI migrate に任せると楽
- 本番DBは token 管理と適用手順を厳格に分けるべき
WSL に慣れているなら Turso CLI を使う方が標準的です。WSL の学習コストを今は避けたい場合は、「Web コンソール + @libsql/client」の構成が現実的な選択肢になります。