Sprint Cycle 18

Fly Postgres + 自前認証 + APIデプロイ

2026-02-24 5 min read

概要

Sprint Cycle 18では、Supabase依存からの脱却を完遂しました。Fly Postgres(PostgreSQL 17.7)をNRTリージョンにセットアップし、auth.usersやRLSポリシーを除去して自前のusersテーブルを作成。JWT自前発行とbcryptパスワード認証を実装し、signup/loginエンドポイントを新設しました。ApiError enumの拡張と3つの認証テストを追加し、全18テスト合格。最終的にAPI本番環境をmiseban-ai-api.fly.devにデプロイ完了しました。

対応内容状態
Fly Postgres (PostgreSQL 17.7) NRTリージョンセットアップ完了
独自スキーマ移行: auth.users/RLS除去、自前usersテーブル作成完了
JWT自前発行 + bcryptパスワード認証 (signup/login)完了
ApiError enum拡張 + 認証テスト3件追加 (18テスト全合格)完了
API本番デプロイ: miseban-ai-api.fly.dev完了

1. Fly Postgres (PostgreSQL 17.7) NRTリージョンセットアップ

これまでSupabaseのマネージドPostgreSQLに依存していましたが、今回のスプリントでFly.io上に自前のPostgresクラスタを構築しました。

Fly Postgresはアプリと同一プラットフォーム上で動作するため、ネットワークホップが最小限に抑えられます。これにより、DB接続のレイテンシが大幅に改善されました。また、Supabaseの無料枠制限やRLSの複雑さから解放され、シンプルなアーキテクチャを実現しています。

2. 独自スキーマ移行

Supabase固有のauth.usersテーブルやRLS(Row Level Security)ポリシーを完全に除去し、自前のスキーマに移行しました。

-- Supabase依存を除去した新しいusersテーブル
CREATE TABLE users (
    id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
    email TEXT UNIQUE NOT NULL,
    password_hash TEXT NOT NULL,
    store_name TEXT,
    tier TEXT NOT NULL DEFAULT 'free',
    created_at TIMESTAMPTZ NOT NULL DEFAULT now(),
    updated_at TIMESTAMPTZ NOT NULL DEFAULT now()
);

Supabaseのauth.usersスキーマは多くの隠れた依存関係(トリガー、関数、RLSポリシー)を持っており、デバッグやマイグレーションの障害になっていました。自前テーブルに移行したことで、スキーマの全体像が明確になり、マイグレーションの管理も容易になっています。

RLSポリシーの除去

Supabase環境ではRLSポリシーによるアクセス制御を行っていましたが、APIサーバーがDB接続を一元管理する構成では不要です。RLSを除去し、アクセス制御はAPIレイヤーのミドルウェアで一括管理する方針に切り替えました。これにより「RLSが204を返すが実際には書き込まれていない」というサイレント失敗の問題も根本的に解消されます。

3. JWT自前発行 + bcryptパスワード認証

Supabase Authに代わる認証基盤として、JWT自前発行とbcryptパスワードハッシュを実装しました。

// POST /api/v1/auth/signup
async fn signup(Json(req): Json<SignupRequest>) -> Result<Json<AuthResponse>, ApiError> {
    let password_hash = bcrypt::hash(&req.password, 12)?;
    let user = sqlx::query_as!(User, /* INSERT INTO users ... */)
        .fetch_one(&pool).await?;
    let token = encode_jwt(&user.id, &jwt_secret)?;
    Ok(Json(AuthResponse { token, user }))
}

// POST /api/v1/auth/login
async fn login(Json(req): Json<LoginRequest>) -> Result<Json<AuthResponse>, ApiError> {
    let user = find_user_by_email(&req.email).await?;
    bcrypt::verify(&req.password, &user.password_hash)?;
    let token = encode_jwt(&user.id, &jwt_secret)?;
    Ok(Json(AuthResponse { token, user }))
}

Supabase Authへの外部HTTPコールが不要になったため、認証フローのレイテンシが改善されました。また、トークンの有効期限やクレーム構造を完全に制御できるようになっています。

4. ApiError enum拡張 + 認証テスト追加

認証機能の実装に伴い、エラーハンドリングを強化しました。

#[derive(Debug)]
enum ApiError {
    Internal(String),
    NotFound(String),
    Unauthorized(String),  // NEW
    BadRequest(String),    // NEW
    // ...
}

新規テスト3件

認証フローをカバーする3つのテストを追加し、テスト合計を18件に引き上げました。

これらのテストにより、認証フローの正常系と異常系の両方がカバーされています。既存の15テストへの影響はなく、全18テストが合格しています。

5. API本番デプロイ

全ての変更をまとめてmiseban-ai-api.fly.devに本番デプロイを完了しました。

APIサーバー、データベース、ランディングページが全てFly.ioプラットフォーム上に統一されたことで、運用管理がシンプルになりました。

テスト結果

18テスト合格cargo check警告ゼロ。既存テストへの影響はありません。

指標BeforeAfter
テスト合格数15/1518/18
cargo check警告00
新規エンドポイント-2件(signup/login)
DB基盤Supabase PostgreSQLFly Postgres (PG 17.7)
認証基盤Supabase Auth自前JWT + bcrypt
本番URL-miseban-ai-api.fly.dev

Supabase依存を完全に脱却し、Fly Postgres + 自前認証による自立したインフラ構成を実現しました。DB、認証、APIサーバーの全てがFly.ioプラットフォーム上に統一され、運用の簡素化とレイテンシ改善を達成。18テスト全合格で品質を担保しつつ、本番デプロイも完了しています。

← ブログ一覧に戻る 無料で始める →