T-CREATOR

Prisma Driver Adapters 導入手順:libSQL/Turso・Neon の最短セットアップ

Prisma Driver Adapters 導入手順:libSQL/Turso・Neon の最短セットアップ

Prisma は長年、データベース接続に TCP(Transmission Control Protocol)を使用してきました。しかし、エッジやサーバーレス環境では TCP 接続が利用できないケースが増えています。そんな課題を解決するために登場したのが「Driver Adapters」です。

この記事では、Prisma Driver Adapters の導入方法を libSQL/Turso と Neon を中心に詳しく解説します。最短でセットアップを完了できるよう、具体的な手順とサンプルコードを交えて説明しますので、ぜひ最後までご覧ください。

背景

Prisma Driver Adapters とは

Prisma Driver Adapters は、Prisma Client と JavaScript データベースドライバーの間で「翻訳者」として機能する仕組みです。従来の TCP 接続ではなく、HTTP や WebSocket を使ってデータベースに接続できるようになりました。

この技術により、以下のような環境でも Prisma が利用可能になります。

#環境説明
1エッジ環境Cloudflare Workers、Vercel Edge Functions など
2サーバーレス環境AWS Lambda、Vercel Serverless Functions など
3分散データベースTurso、Neon、PlanetScale など

Driver Adapters の仕組み

以下の図は、Prisma Client がどのように Driver Adapters を経由してデータベースに接続するかを示しています。

mermaidflowchart LR
  app["アプリケーション"] -->|クエリ実行| client["Prisma Client"]
  client -->|リクエスト変換| adapter["Driver Adapter"]
  adapter -->|HTTP/WebSocket| driver["データベースドライバー"]
  driver -->|接続| db[("データベース")]
  db -->|結果| driver
  driver -->|レスポンス| adapter
  adapter -->|データ変換| client
  client -->|結果| app

従来は Prisma Client が直接 TCP 経由でデータベースに接続していましたが、Driver Adapters を挟むことで、JavaScript ドライバーを介した柔軟な接続が可能になりました。

サポートされている Driver Adapters

Prisma は以下のデータベースドライバーに対応しています。

データベース Driver Adapters

#データベースドライバーアダプターパッケージ
1PostgreSQLpg@prisma/adapter-pg
2MySQL/MariaDBmariadb@prisma/adapter-mariadb
3SQLitebetter-sqlite3@prisma/adapter-better-sqlite3
4SQLitelibSQL@prisma/adapter-libsql
5MS SQL Servernode-mssql@prisma/adapter-mssql

サーバーレス Driver Adapters

#サービスアダプターパッケージ特徴
1Neon@prisma/adapter-neonWebSocket 接続対応
2PlanetScale@prisma/adapter-planetscaleHTTP 接続対応
3Cloudflare D1@prisma/adapter-d1エッジ環境最適化

この記事では特に libSQL(Turso)Neon の導入手順に焦点を当てて解説していきます。

課題

従来の Prisma における接続の制約

従来の Prisma は TCP 接続を前提としていたため、以下のような課題がありました。

エッジ環境での動作制限

Cloudflare Workers や Vercel Edge Functions などのエッジ環境では、TCP 接続が利用できません。そのため、従来の Prisma をそのまま使うことができませんでした。

サーバーレス環境でのコールドスタート

サーバーレス環境では、関数が起動するたびに TCP 接続を確立する必要があり、コールドスタート時のレイテンシが増加する問題がありました。

分散データベースへの対応不足

Turso や Neon のような分散データベースは、HTTP や WebSocket を使った接続に最適化されています。従来の TCP 接続では、これらのデータベースの特性を十分に活かせませんでした。

解決すべき技術的な問題

以下の図は、従来の接続方式と Driver Adapters を使った接続方式の違いを示しています。

mermaidflowchart TD
  subgraph old["従来の接続方式"]
    app1["アプリケーション"] -->|TCP接続必須| db1[("データベース")]
  end

  subgraph new_approach["Driver Adapters 接続方式"]
    app2["アプリケーション"] -->|HTTP/WebSocket| adapter2["Driver Adapter"]
    adapter2 -->|柔軟な接続| db2[("データベース")]
  end

  old -.->|課題| issues["★ エッジ環境で動作しない<br/>★ コールドスタートが遅い<br/>★ 分散DBに非対応"]
  new_approach -.->|解決| solutions["★ エッジ環境で動作<br/>★ 高速な接続確立<br/>★ 分散DBに最適化"]

これらの課題を解決するために、Prisma Driver Adapters が開発されました。次のセクションでは、具体的な解決策を見ていきましょう。

解決策

Driver Adapters による接続の柔軟化

Prisma Driver Adapters を使用することで、TCP 接続に依存しない柔軟なデータベース接続が実現できます。これにより、エッジ環境やサーバーレス環境でも Prisma を利用できるようになりました。

libSQL(Turso)と Neon の選択基準

どちらのデータベースを選ぶべきか迷う方も多いでしょう。以下の表で比較してみましょう。

#項目libSQL(Turso)Neon
1ベース DBSQLite(libSQL fork)PostgreSQL
2接続方式HTTP/WebSocketWebSocket/HTTP
3エッジ対応★★★★★ 組み込みレプリカ対応★★★★☆ WebSocket 対応
4スケーリング地理的分散に強いオートスケーリング対応
5料金無料枠あり(500DB まで)無料枠あり(0.5GB まで)
6適した用途グローバル展開、低レイテンシ重視PostgreSQL エコシステム重視

選択のポイントは以下のとおりです。

libSQL(Turso)を選ぶべきケース

  • グローバルにユーザーが分散しているアプリケーション
  • SQLite の軽量性を活かしたい場合
  • エッジ環境での超低レイテンシが必要な場合

Neon を選ぶべきケース

  • PostgreSQL の高度な機能が必要な場合
  • 既存の PostgreSQL ベースのアプリケーションを移行したい場合
  • オートスケーリングを活用したい場合

Driver Adapters の基本的な使い方

Driver Adapters を使う際の基本的な流れを図で確認しましょう。

mermaidsequenceDiagram
  participant App as アプリケーション
  participant PC as Prisma Client
  participant Adapter as Driver Adapter
  participant Driver as データベースドライバー
  participant DB as データベース

  App->>PC: クエリ実行リクエスト
  PC->>Adapter: クエリを渡す
  Adapter->>Driver: ドライバー形式に変換
  Driver->>DB: HTTP/WebSocket経由で接続
  DB-->>Driver: 結果を返す
  Driver-->>Adapter: 結果を渡す
  Adapter-->>PC: Prisma形式に変換
  PC-->>App: 結果を返す

このフローにより、Prisma Client は内部的な接続方式を意識することなく、一貫した API でデータベース操作ができます。

次のセクションでは、実際のセットアップ手順を具体的に見ていきましょう。

具体例

このセクションでは、libSQL(Turso)と Neon の実際のセットアップ手順を順を追って解説します。

libSQL(Turso)のセットアップ手順

ステップ 1:Turso CLI のインストール

まず、Turso CLI をインストールします。

bash# macOS / Linux
curl -sSfL https://get.tur.so/install.sh | bash

# Windows (PowerShell)
irm get.tur.so/install.ps1 | iex

インストール後、Turso にログインしましょう。

bashturso auth login

ブラウザが開き、GitHub アカウントで認証できます。

ステップ 2:Turso データベースの作成

新しいデータベースを作成します。

bashturso db create turso-prisma-db

データベースが作成されると、接続情報が表示されます。次のコマンドで接続 URL を確認できます。

bashturso db show turso-prisma-db

認証トークンを取得します。

bashturso db tokens create turso-prisma-db

このトークンは後ほど環境変数に設定するため、コピーしておいてください。

ステップ 3:必要なパッケージのインストール

プロジェクトに必要なパッケージをインストールします。

bashyarn add @prisma/client @prisma/adapter-libsql
yarn add -D prisma

これらのパッケージには以下の役割があります。

#パッケージ役割
1@prisma/clientPrisma のクライアントライブラリ
2@prisma/adapter-libsqllibSQL 用の Driver Adapter
3prismaPrisma CLI(開発時のみ使用)

ステップ 4:環境変数の設定

プロジェクトルートに .env ファイルを作成します。

bash# .env ファイルの作成
touch .env

以下の内容を .env ファイルに記述します。

env# Turso データベース接続情報
TURSO_DATABASE_URL="libsql://your-database.turso.io"
TURSO_AUTH_TOKEN="your_auth_token_here"

# Prisma 用の接続文字列(マイグレーション用)
DATABASE_URL="file:./dev.db"

TURSO_DATABASE_URLTURSO_AUTH_TOKEN には、先ほど取得した値を設定してください。

ステップ 5:Prisma スキーマの作成

Prisma を初期化します。

bashnpx prisma init --datasource-provider sqlite

prisma​/​schema.prisma ファイルが作成されます。以下のように編集しましょう。

prismagenerator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "sqlite"
  url      = env("DATABASE_URL")
}

サンプルとして、User モデルを追加します。

prismamodel User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

このモデルは、ユーザー情報を管理するためのシンプルなテーブルを定義しています。

ステップ 6:データベースのマイグレーション

スキーマをデータベースに反映させます。

bashnpx prisma db push

このコマンドにより、Turso データベースに User テーブルが作成されます。

ステップ 7:Prisma Client の設定

src​/​lib​/​prisma.ts(または任意のファイル名)を作成します。

typescript// 必要なパッケージのインポート
import { PrismaClient } from '@prisma/client';
import { PrismaLibSQL } from '@prisma/adapter-libsql';

次に、アダプターを初期化します。

typescript// libSQL アダプターの設定
const adapter = new PrismaLibSQL({
  url: process.env.TURSO_DATABASE_URL as string,
  authToken: process.env.TURSO_AUTH_TOKEN as string,
});

urlauthToken には環境変数から取得した値を渡します。これにより、Turso データベースへの接続が確立されます。

最後に、Prisma Client を初期化します。

typescript// Prisma Client の初期化
const prisma = new PrismaClient({
  adapter,
  log: ['query', 'error', 'warn'], // ログレベルを設定(開発時のみ推奨)
});

export default prisma;

adapter オプションに先ほど作成したアダプターを渡すことで、Prisma Client が libSQL 経由でデータベースに接続できるようになります。

ステップ 8:動作確認

簡単なクエリを実行して、接続が正常に動作するか確認しましょう。

typescript// src/index.ts
import prisma from './lib/prisma';

async function main() {
  // ユーザーを作成
  const user = await prisma.user.create({
    data: {
      email: 'test@example.com',
      name: 'Test User',
    },
  });

  console.log('作成されたユーザー:', user);
}

エラーハンドリングとクリーンアップ処理を追加します。

typescriptmain()
  .catch((error) => {
    console.error('エラーが発生しました:', error);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });

スクリプトを実行します。

bashnpx tsx src/index.ts

正常に動作すれば、作成されたユーザー情報がコンソールに表示されます。

Neon のセットアップ手順

次に、Neon を使った Driver Adapters のセットアップ方法を見ていきましょう。

ステップ 1:Neon プロジェクトの作成

Neon のコンソールにアクセスし、新しいプロジェクトを作成します。

プロジェクトが作成されたら、「Connect」ボタンをクリックして接続文字列を取得しましょう。

ステップ 2:接続文字列の取得

Neon では以下の 2 種類の接続文字列が提供されます。

#種類用途形式
1通常の接続文字列マイグレーション、開発環境postgresql:​/​​/​user:pass@host​/​db
2Pooled 接続文字列サーバーレス、本番環境postgresql:​/​​/​user:pass@host-pooler​/​db

サーバーレス環境では、Pooled 接続文字列を使用することが推奨されます。

ステップ 3:必要なパッケージのインストール

Neon 用のパッケージをインストールします。

bashyarn add @prisma/client @prisma/adapter-neon @neondatabase/serverless
yarn add -D prisma ws

各パッケージの役割は以下のとおりです。

#パッケージ役割
1@prisma/adapter-neonNeon 用の Driver Adapter
2@neondatabase/serverlessNeon のサーバーレスドライバー
3wsWebSocket 接続用ライブラリ

ステップ 4:環境変数の設定

.env ファイルを作成します。

env# Neon データベース接続情報(マイグレーション用)
DATABASE_URL="postgresql://user:password@host.neon.tech/dbname?sslmode=require"

# Neon Pooled 接続文字列(サーバーレス用)
DATABASE_URL_POOLED="postgresql://user:password@host-pooler.neon.tech/dbname?sslmode=require"

sslmode=require を追加することで、SSL 接続が強制されます。セキュリティ向上のため、channel_binding=require も追加することが推奨されます。

envDATABASE_URL="postgresql://user:password@host.neon.tech/dbname?sslmode=require&channel_binding=require"
DATABASE_URL_POOLED="postgresql://user:password@host-pooler.neon.tech/dbname?sslmode=require&channel_binding=require"

ステップ 5:Prisma スキーマの作成

Prisma を PostgreSQL で初期化します。

bashnpx prisma init --datasource-provider postgresql

prisma​/​schema.prisma が作成されます。

prismagenerator client {
  provider = "prisma-client-js"
}

datasource db {
  provider = "postgresql"
  url      = env("DATABASE_URL")
}

サンプルモデルを追加しましょう。

prismamodel Post {
  id        Int      @id @default(autoincrement())
  title     String
  content   String?
  published Boolean  @default(false)
  authorId  Int
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt

  author    User     @relation(fields: [authorId], references: [id])
}

model User {
  id        Int      @id @default(autoincrement())
  email     String   @unique
  name      String?
  posts     Post[]
  createdAt DateTime @default(now())
  updatedAt DateTime @updatedAt
}

このスキーマでは、UserPost のリレーションを定義しています。

ステップ 6:データベースのマイグレーション

スキーマをデータベースに反映させます。

bashnpx prisma migrate dev --name init

このコマンドにより、マイグレーションファイルが作成され、Neon データベースにテーブルが作成されます。

ステップ 7:Prisma Client の設定(サーバーレス環境用)

src​/​lib​/​prisma.ts を作成します。

typescript// 必要なパッケージのインポート
import { PrismaClient } from '@prisma/client';
import { PrismaNeon } from '@prisma/adapter-neon';
import { Pool } from '@neondatabase/serverless';
import ws from 'ws';

WebSocket の設定を行います。

typescript// WebSocket の設定(Node.js 環境で必要)
if (typeof WebSocket === 'undefined') {
  (global as any).WebSocket = ws;
}

この設定により、Node.js 環境でも WebSocket を使用できるようになります。

次に、接続プールを作成します。

typescript// Neon の接続プールを作成
const pool = new Pool({
  connectionString: process.env.DATABASE_URL_POOLED,
});

接続プールを使うことで、サーバーレス環境でも効率的にデータベース接続を管理できます。

アダプターを初期化します。

typescript// Neon アダプターの設定
const adapter = new PrismaNeon(pool);

最後に、Prisma Client を初期化します。

typescript// Prisma Client の初期化
const prisma = new PrismaClient({
  adapter,
  log: ['query', 'error', 'warn'],
});

export default prisma;

ステップ 8:動作確認

接続が正常に動作するか確認しましょう。

typescript// src/index.ts
import prisma from './lib/prisma';

async function main() {
  // ユーザーを作成
  const user = await prisma.user.create({
    data: {
      email: 'neon@example.com',
      name: 'Neon User',
    },
  });

  console.log('作成されたユーザー:', user);
}

リレーションを含むクエリも試してみましょう。

typescript// ユーザーと投稿を同時に作成
const userWithPost = await prisma.user.create({
  data: {
    email: 'author@example.com',
    name: 'Post Author',
    posts: {
      create: {
        title: 'Neon と Prisma で始めるサーバーレス開発',
        content:
          'Driver Adapters を使うことで、エッジ環境でも快適に開発できます。',
        published: true,
      },
    },
  },
  include: {
    posts: true,
  },
});

console.log('作成されたユーザーと投稿:', userWithPost);

エラーハンドリングを追加します。

typescriptmain()
  .catch((error) => {
    console.error('エラーが発生しました:', error);
    process.exit(1);
  })
  .finally(async () => {
    await prisma.$disconnect();
  });

スクリプトを実行します。

bashnpx tsx src/index.ts

正常に動作すれば、ユーザーと投稿の情報がコンソールに表示されます。

エッジ環境でのデプロイ(Vercel Edge Functions)

最後に、Vercel Edge Functions で動作させる方法を見てみましょう。

ステップ 1:Next.js プロジェクトの設定

Next.js の API Routes を Edge Runtime で動作させます。

typescript// app/api/users/route.ts
import { NextRequest, NextResponse } from 'next/server';
import prisma from '@/lib/prisma';

// Edge Runtime を指定
export const runtime = 'edge';

GET リクエストのハンドラーを実装します。

typescriptexport async function GET(request: NextRequest) {
  try {
    // ユーザー一覧を取得
    const users = await prisma.user.findMany({
      take: 10,
      orderBy: {
        createdAt: 'desc',
      },
    });

    return NextResponse.json({ users });
  } catch (error) {
    console.error('エラー:', error);
    return NextResponse.json(
      { error: 'ユーザーの取得に失敗しました' },
      { status: 500 }
    );
  }
}

このエンドポイントは、最新のユーザー 10 件を取得して返します。

POST リクエストのハンドラーも追加しましょう。

typescriptexport async function POST(request: NextRequest) {
  try {
    const body = await request.json();

    // ユーザーを作成
    const user = await prisma.user.create({
      data: {
        email: body.email,
        name: body.name,
      },
    });

    return NextResponse.json({ user }, { status: 201 });
  } catch (error) {
    console.error('エラー:', error);
    return NextResponse.json(
      { error: 'ユーザーの作成に失敗しました' },
      { status: 500 }
    );
  }
}

ステップ 2:Vercel へのデプロイ

環境変数を Vercel に設定します。

bash# Vercel CLI でログイン
vercel login

# 環境変数を設定
vercel env add DATABASE_URL_POOLED

プロンプトに従って、Neon の Pooled 接続文字列を入力してください。

デプロイを実行します。

bashvercel deploy

デプロイが完了すると、Edge Functions として動作する API エンドポイントが作成されます。

セットアップフロー全体図

これまでの手順を図にまとめると、以下のようになります。

mermaidflowchart TD
  start["セットアップ開始"] --> choice{"データベース選択"}

  choice -->|libSQL/Turso| turso_start["Turso CLI インストール"]
  choice -->|Neon| neon_start["Neon プロジェクト作成"]

  turso_start --> turso_db["データベース作成"]
  turso_db --> turso_packages["パッケージインストール<br/>@prisma/adapter-libsql"]
  turso_packages --> turso_env["環境変数設定<br/>TURSO_DATABASE_URL<br/>TURSO_AUTH_TOKEN"]

  neon_start --> neon_conn["接続文字列取得"]
  neon_conn --> neon_packages["パッケージインストール<br/>@prisma/adapter-neon<br/>@neondatabase/serverless"]
  neon_packages --> neon_env["環境変数設定<br/>DATABASE_URL_POOLED"]

  turso_env --> schema["Prisma スキーマ作成"]
  neon_env --> schema

  schema --> migrate["マイグレーション実行"]
  migrate --> client_setup["Prisma Client 設定"]
  client_setup --> test["動作確認"]
  test --> deploy["デプロイ"]
  deploy --> task_end["セットアップ完了"]

このフローに従うことで、libSQL(Turso)と Neon のどちらを選択しても、スムーズにセットアップが完了します。

まとめ

Prisma Driver Adapters は、エッジ環境やサーバーレス環境でデータベースを活用するための強力な機能です。この記事では、libSQL(Turso)と Neon の導入手順を具体的に解説しました。

重要なポイントを振り返りましょう。

libSQL(Turso)のポイント

  • グローバル展開や低レイテンシが求められるアプリケーションに最適です
  • SQLite ベースで軽量、組み込みレプリカによりエッジ環境で高速動作します
  • @prisma​/​adapter-libsql を使うことで簡単に統合できます

Neon のポイント

  • PostgreSQL の高度な機能が必要な場合に適しています
  • WebSocket 接続によりサーバーレス環境で効率的に動作します
  • Pooled 接続文字列を使うことでコネクション管理が最適化されます

共通のベストプラクティス

  • 環境変数を適切に設定し、機密情報をコードに含めないようにしましょう
  • エラーハンドリングを必ず実装し、本番環境でのトラブルに備えてください
  • ログレベルを適切に設定し、開発時と本番時で使い分けましょう

Driver Adapters を活用することで、これまで制約のあったエッジ環境でも Prisma の強力な ORM 機能を最大限に活用できるようになります。ぜひ実際のプロジェクトで試してみてください。

関連リンク