> ## Documentation Index
> Fetch the complete documentation index at: https://clickhouse.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# ClickHouse Managed Postgres で Prisma を使用する

> Prisma ORM を使用して TypeScript アプリを ClickHouse Managed Postgres に接続し、Prisma Migrate で移行を実行したうえで、TLS 検証を有効にした PgBouncer 経由でクエリを実行します

[ベータ](https://clickhouse.com/cloud/postgres)

[Prisma ORM](https://www.prisma.io/orm) は、宣言的なスキーマ、移行ツール (Prisma Migrate)、自動生成される型安全なクライアントを備えた TypeScript 向けの ORM です。このガイドでは、Prisma を ClickHouse Managed Postgres に接続し、移行によってテーブルを作成したうえで、スクリプトと小規模な HTTP エンドポイントからそのテーブルにクエリを実行します。

このガイドでは、現行の安定版リリースである Prisma ORM 7 (`7.10.0` で動作確認済み) を使用します。

## 前提条件

* Node.js 20.19、22.12、または 24 以降
* ClickHouse Managed Postgres サービス
* データベースを作成するための [`psql`](https://www.postgresql.org/download/)。`CREATE DATABASE` ステートメントは [SQL コンソール](https://clickhouse.com/docs/ja/integrations/connectors/sql-clients/sql-console.md) で実行することもできます。
* macOS の場合: Prisma Migrate を実行するための [Docker](https://docs.docker.com/get-started/get-docker/) ([移行を実行する](#migrate)を参照)

## ClickHouse Managed Postgres サービスを作成する

ClickHouse Cloud コンソールで **New service** をクリックし、**Postgres** を選択します。インスタンスは数分で利用可能になります。詳しい手順については、[クイックスタート](https://clickhouse.com/docs/ja/products/managed-postgres/quickstart.md)を参照してください。

## 接続情報を取得する

サービスの左サイドバーで **Connect** をクリックします。表示されるモーダルには、ユーザー名、パスワード、サーバー、ポートのほか、そのまま使える接続文字列が表示されます。

Prisma にはデータベースと通信するコンポーネントが 2 つあるため、このガイドでは 2 種類の接続を使用します。

* **アプリケーション (Prisma Client)** は、ポート `6432` で **PgBouncer 経由** で接続します。PgBouncer が接続をプールするため、多数のアプリケーションプロセスやサーバーレスインスタンスで少数の Postgres バックエンドを共有できます。
* **Prisma CLI (Prisma Migrate)** は、ポート `5432` で **直接** 接続します。Prisma Migrate は実行中にセッションレベルのアドバイザリロックを取得します。PgBouncer のトランザクションプーリングモードでは、このロックがプールされたバックエンド上に保持されたまま、そのバックエンドが他のクライアントにも割り当てられるため、後続の移行がこのロックによってブロックされてしまいます。

モーダル上部で **Directly** と **via PgBouncer** を切り替えると、それぞれのポートを確認できます。サーバーと認証情報はどちらの接続でも共通で、異なるのはポートだけです。

**via PgBouncer** を選択した状態で **Download CA certificate** をクリックします。**Directly** を選択している場合は、先に **Use SSL** をオンにするとボタンが表示されます。ファイル名は `<service-name>-ca-certificate.pem` です。このファイルは **Settings → CA Certificate** からも取得できます。この証明書はインスタンスごとに固有で、`sslmode=verify-full` で接続する際に使用します。これにより、接続先が自分のサーバーであることが検証されます。

## プロジェクトをセットアップする

TypeScript プロジェクトを作成し、Prisma CLI、Prisma Client、[node-postgres](https://node-postgres.com/) ドライバーアダプター、`dotenv` をインストールします。

```bash theme={null}
mkdir hello-prisma
cd hello-prisma
npm init -y
npm pkg set type=module
npm install typescript tsx @types/node @types/pg --save-dev
npm install prisma@7 --save-dev
npm install @prisma/client@7 @prisma/adapter-pg pg dotenv
```

> [!NOTE]
>
> `prisma@7` と `@prisma/client@7` は、バージョンを明示してインストールしてください。本ガイドの執筆時点では、`prisma` の npm `latest` タグは Prisma 8 のリリース候補版を指しており、本ガイドとはセットアップ方法が異なります。

`tsconfig.json` を作成します。

```json theme={null}
{
  "compilerOptions": {
    "module": "ESNext",
    "moduleResolution": "bundler",
    "target": "ES2023",
    "strict": true,
    "esModuleInterop": true,
    "skipLibCheck": true,
    "types": ["node"]
  }
}
```

> [!TIP]
>
> **既存のアプリに追加する場合**
>
> `mkdir`、`npm init`、`tsconfig.json` の手順は不要です。プロジェクト内で `npm install tsx @types/pg prisma@7 --save-dev` と `npm install @prisma/client@7 @prisma/adapter-pg pg dotenv` を実行してから、[Prisma の初期化](#init)に進んでください。

## Prisma を初期化する

**1. prisma init を実行する**

```bash theme={null}
npx prisma init --datasource-provider postgresql --output ../generated/prisma
```

このコマンドを実行すると、`prisma/schema.prisma` と Prisma の設定ファイル `prisma7.config.ts` が作成され、`.env` にはプレースホルダーの `DATABASE_URL` が、`.gitignore` には生成されたクライアントが追加されます (これらのファイルが存在しない場合は新規作成されます) 。あわせて、AI コーディングエージェント向けの Prisma スキルも追加されます。Prisma 7.10 以降では、Prisma 8 のフォーマットとの競合を避けるため、設定ファイル名が `prisma7.config.ts` になっています。

**2. CA 証明書を追加する**

ダウンロードした CA 証明書をプロジェクトのルートに移動し、`ca-certificate.pem` にリネームします。

```bash theme={null}
mv ~/Downloads/<service-name>-ca-certificate.pem ca-certificate.pem
```

証明書の相対パスは、コマンドを実行したディレクトリを基準に解決されます。そのため、このガイドのコマンドはすべてプロジェクトのルートで実行してください。

## 接続を設定する

**1. データベースを作成する**

アプリ用のデータベースを作成します。`<PASSWORD>` とホストは、**Connect** モーダルに表示される値に置き換えてください。

```bash theme={null}
psql "postgresql://postgres:<PASSWORD>@your-instance.pg.clickhouse.cloud:5432/postgres?sslmode=verify-full&sslrootcert=ca-certificate.pem" -c "CREATE DATABASE guide_prisma;"
```

```text theme={null}
CREATE DATABASE
```

**2. 接続 URL を設定する**

`.env` で、`prisma init` が追加したプレースホルダーの `DATABASE_URL` を、次の 2 つの接続 URL に置き換えます。どちらも `guide_prisma` データベースを指します。パスワードには Connect モーダルに表示されるものを使用してください。

```bash theme={null}
# Prisma Client（アプリ）: PgBouncer 経由、ポート 6432
DATABASE_URL="postgresql://postgres:<PASSWORD>@your-instance.pg.clickhouse.cloud:6432/guide_prisma?sslmode=verify-full&sslrootcert=ca-certificate.pem"

# Prisma CLI（移行）: 直接接続、ポート 5432
DIRECT_URL="postgresql://postgres:<PASSWORD>@your-instance.pg.clickhouse.cloud:5432/guide_prisma?sslmode=require&sslaccept=strict&sslcert=ca-certificate.pem"
```

2 つの URL はそれぞれ別のドライバーが読み取るため、TLS パラメータの指定方法が異なります。

* **`DATABASE_URL`** は、`@prisma/adapter-pg` 経由で node-postgres が読み取ります。Connect モーダルに表示されるものと同じ、標準の `sslmode=verify-full&sslrootcert=...` パラメータに対応しています。
* **`DIRECT_URL`** は、Prisma CLI のスキーマエンジンが読み取ります。このエンジンは独自のパラメータを使用し、`sslcert` で CA 証明書へのパスを指定し、`sslaccept=strict` で証明書とホスト名の検証を有効にします。

> [!WARNING]
>
> Prisma CLI 用の URL には `sslmode=verify-full&sslrootcert=...` を使用しないでください。スキーマエンジンは `sslrootcert` を無視するため、`sslaccept=strict` を指定しないとサーバー証明書の検証がまったく行われません。その結果、接続は暗号化されても認証はされない状態になります。

**3. Prisma CLI が直接接続を使用するよう設定する**

`prisma7.config.ts` の内容を次のように置き換えます。

```typescript theme={null}
import "dotenv/config";
import { defineConfig, env } from "prisma/config";

export default defineConfig({
  schema: "prisma/schema.prisma",
  migrations: {
    path: "prisma/migrations",
  },
  datasource: {
    url: env("DIRECT_URL"),
  },
});
```

Prisma 7 では、設定ファイル内の URL は CLI だけが使用します。Prisma Client はドライバーアダプターから接続を取得します。ドライバーアダプターの設定は [データベースにクエリを実行する](#query) で行います。

## スキーマを定義して移行を実行する

**1. モデルを追加する**

`prisma/schema.prisma` の末尾に `Todo` モデルを追加します。

```prisma theme={null}
model Todo {
  id        Int      @id @default(autoincrement())
  title     String
  done      Boolean  @default(false)
  createdAt DateTime @default(now())
}
```

**2. マイグレーションを実行する**

Linux では、Prisma Migrate を直接実行します。

```bash theme={null}
npx prisma migrate dev --name init
```

macOS では、同じコマンドを Linux コンテナー内で実行します。

```bash theme={null}
docker run --rm -it -v "$PWD":/app -w /app node:24 npx prisma migrate dev --name init
```

> [!WARNING]
>
> ClickHouse Managed Postgres は TLS 1.3 のみをサポートしています。macOS では、Prisma CLI のスキーマエンジンがシステムの TLS ライブラリを使用するため、この条件では接続できません。`P1011: Error opening a TLS connection: One or more parameters passed to a function were not valid` というエラーで失敗するか、`sslcert` を削除した場合は `bad protocol version` というエラーで失敗します ([prisma/orm#29600](https://github.com/prisma/orm/issues/29600)) 。この問題が影響するのは、`prisma migrate` や `prisma db pull` など、データベースに接続する CLI コマンドのみです。Prisma Client は node-postgres 経由で接続するため、影響を受けません。この問題は、CLI を Linux コンテナー内、または Linux ベースの CI パイプライン内で実行することで回避できます。

Prisma は `prisma/migrations/` に SQL の移行ファイルを作成し、適用します。

```text theme={null}
Applying migration `20260930165244_init`

The following migration(s) have been created and applied from new schema changes:

prisma/migrations/
  └─ 20260930165244_init/
    └─ migration.sql

Your database is now in sync with your schema.
```

**3. Prisma Client を生成する**

```bash theme={null}
npx prisma generate
```

クライアントは `generated/prisma` に生成されます。このコマンドはデータベースに接続しないため、どのプラットフォームでも実行できます。

## データベースにクエリを実行する

**1. Prisma Client を作成する**

`lib/prisma.ts` を作成します。`PrismaPg` アダプターは、`DATABASE_URL` を使用して PgBouncer 経由で接続します。

```typescript theme={null}
import "dotenv/config";
import { PrismaPg } from "@prisma/adapter-pg";
import { PrismaClient } from "../generated/prisma/client";

const adapter = new PrismaPg({ connectionString: process.env.DATABASE_URL });

export const prisma = new PrismaClient({ adapter });
```

> [!TIP]
>
> **PgBouncer の設定は不要**
>
> `@prisma/adapter-pg` は各クエリを名前なしのプリペアドステートメントとして送信し、`DEALLOCATE` を一切実行しないため、PgBouncer のトランザクションプーリングモードでも問題なく動作します。プールされた複数のバックエンドで数百種類のクエリを同時実行しても、エラーは発生しません。旧バージョンの Prisma で使われていた `pgbouncer=true` URL パラメータは不要で、ドライバーアダプターでは指定しても効果はありません。

**2. CRUD クエリを実行する**

`script.ts` を作成します。

```typescript theme={null}
import { prisma } from "./lib/prisma";

async function main() {
  // 作成
  const todo = await prisma.todo.create({
    data: { title: "Connect Prisma to ClickHouse Managed Postgres" },
  });
  console.log("Created:", todo);

  // 読み取り
  const open = await prisma.todo.findMany({ where: { done: false } });
  console.log("Open todos:", open.length);

  // 更新
  const updated = await prisma.todo.update({
    where: { id: todo.id },
    data: { done: true },
  });
  console.log("Updated:", updated);

  // 削除
  await prisma.todo.delete({ where: { id: todo.id } });
  console.log("Deleted todo", todo.id);
}

main().finally(() => prisma.$disconnect());
```

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

```bash theme={null}
npx tsx script.ts
```

```text theme={null}
Created: {
  id: 1,
  title: 'Connect Prisma to ClickHouse Managed Postgres',
  done: false,
  createdAt: 2026-09-30T16:52:57.116Z
}
Open todos: 1
Updated: {
  id: 1,
  title: 'Connect Prisma to ClickHouse Managed Postgres',
  done: true,
  createdAt: 2026-09-30T16:52:57.116Z
}
Deleted todo 1
```

**3. HTTP でデータを配信する**

`server.ts` を作成します。これは、`POST /todos` で todo を作成し、すべての `GET` リクエストに対して todo の一覧を返す最小構成の HTTP サーバーです。

```typescript theme={null}
import { createServer } from "node:http";
import { prisma } from "./lib/prisma";

const port = Number(process.env.PORT ?? 3000);

createServer(async (req, res) => {
  if (req.method === "POST" && req.url === "/todos") {
    let body = "";
    for await (const chunk of req) body += chunk;
    const todo = await prisma.todo.create({ data: { title: JSON.parse(body).title } });
    res.writeHead(201, { "Content-Type": "application/json" });
    res.end(JSON.stringify(todo));
    return;
  }

  const todos = await prisma.todo.findMany({ orderBy: { id: "asc" } });
  res.writeHead(200, { "Content-Type": "application/json" });
  res.end(JSON.stringify(todos, null, 2));
}).listen(port, () => console.log(`Listening on http://localhost:${port}`));
```

サーバーを起動します。

```bash theme={null}
npx tsx server.ts
```

別の端末を開き、todo を 2 件追加します。

```bash theme={null}
curl -X POST localhost:3000/todos -H "Content-Type: application/json" -d '{"title": "Try Prisma with ClickHouse Managed Postgres"}'
curl -X POST localhost:3000/todos -H "Content-Type: application/json" -d '{"title": "Add a read replica"}'
```

ブラウザで [http://localhost:3000/todos](http://localhost:3000/todos) を開くと、追加した todo を確認できます。レスポンスは次のようになります。

```json theme={null}
[
  {
    "id": 2,
    "title": "Try Prisma with ClickHouse Managed Postgres",
    "done": false,
    "createdAt": "2026-09-30T16:53:06.098Z"
  },
  {
    "id": 3,
    "title": "Add a read replica",
    "done": false,
    "createdAt": "2026-09-30T16:53:06.184Z"
  }
]
```

## SQL コンソールで確認する

ClickHouse Cloud コンソールで対象サービスの **SQL console** を開き、データベースと `public` スキーマを展開して `Todo` テーブルを選択します。あわせて `_prisma_migrations` テーブルも表示されます。これは、Prisma Migrate が適用済みの移行を記録するテーブルです。

`Todo` テーブルには、HTTP エンドポイント経由で追加した 2 行が格納されています。

| id | title | done | createdAt |
| - | - | - | - |
| 2 | Try Prisma with ClickHouse Managed Postgres | false | 2026-09-30 16:53:06.098 |
| 3 | Add a read replica | false | 2026-09-30 16:53:06.184 |

## トラブルシューティング

| エラー | 原因と対処法 |
| - | - |
| `P1011: Error opening a TLS connection: One or more parameters passed to a function were not valid` または `bad protocol version` | Prisma CLI が macOS 上で実行されています。[移行を実行する](#migrate) で示しているように、Linux コンテナー内で実行してください。 |
| `P1011: ... certificate verify failed` | Prisma CLI がサーバーを検証できていません。`DIRECT_URL` の `sslcert` が、インスタンスの CA 証明書を指しているか確認してください。 |
| `P1011: ... cert file not found` | `DIRECT_URL` の `sslcert` に指定したパスが正しくありません。プロジェクトのルートから CLI を実行するか、絶対パスを指定してください。 |
| `unable to verify the first certificate` | Prisma Client がサーバーを検証できていません。`DATABASE_URL` の `sslrootcert` が、インスタンスの CA 証明書を指しているか確認してください。 |
| `ENOENT: no such file or directory` | `DATABASE_URL` の `sslrootcert` に指定したパスが正しくありません。プロジェクトのルートからアプリケーションを実行するか、絶対パスを指定してください。 |

## 次のステップ

* [接続](https://clickhouse.com/docs/ja/products/managed-postgres/connection.md): 接続文字列、PgBouncer、TLS
* [設定](https://clickhouse.com/docs/ja/products/managed-postgres/settings.md): Postgres と PgBouncer のパラメータをチューニングする
* [読み取りレプリカ](https://clickhouse.com/docs/ja/products/managed-postgres/read-replicas.md): 読み取り負荷の高いワークロードをスケールさせる
* [ローカル開発](https://clickhouse.com/docs/ja/products/managed-postgres/local-development.md): Docker 上のローカル Postgres を使って開発する
* [本番環境での Prisma Migrate](https://www.prisma.io/docs/orm/prisma-migrate/workflows/development-and-production): CI パイプラインで `prisma migrate deploy` を使用する
