Strapiを超えるとき:Payload + Supabaseを使った構築

過去数年間、少なくとも十数件のクライアントプロジェクトでStrapiをセットアップしてきました。はじめるのに最適なCMS です――フレンドリーな管理パネル、まともなプラグインエコシステム、しっかりしたドキュメント。しかし、だいたい18ヶ月の時点で、一緒に仕事をしたほぼすべてのチームが壁にぶつかります。マイグレーションが痛くなり、カスタマイズがハックに見え、TypeScriptが好きなフロントエンド開発者たちが開発体験について不平を言い始めるのです。これが耳に馴染みがあれば、あなたは一人ではありません。Strapiを超えた兆候と、それ以上に重要なことに、代わりに何を構築するかについて説明させてください。

When You've Outgrown Strapi CMS: Building with Payload + Supabase

目次

蜜月期:なぜStrapiは初期段階で機能するのか

正当な場所に信用を与えましょう。Strapiには65K以上のGitHubスターがある理由があります。新しいコンテンツ駆動型プロジェクトを立ち上げるとき、Content-Type Builderは本当に有用です。GUIをクリックして、いくつかのフィールドを定義すると、すぐにREST APIとGraphQL APIが得られます。非技術的なコンテンツエディターは管理パネルにログインして、1時間以内に公開を開始できます。

初期段階のスタートアップ、マーケティングサイト、ブログの場合、Strapiは完全に合理的な選択です。PostgreSQL、MySQL、MariaDB、SQLiteをサポートしています。プラグインマーケットプレイスには100以上のコミュニティ拡張機能があります。コミュニティ版はMITライセンスの下で無料です。

私はStrapi を何度も推奨しています。ここに来たのはそれをけなすためではありません。次に何が起こるかについて話すためにここに来ました。

Strapiを超えた6つの兆候

これらは私が繰り返し見るパターンです。これらの3つ以上があなたに当てはまる場合は、マイグレーションの計画を開始する時間です。

1. マイグレーションがあなたを緊張させる

v4からv5へのアップグレードは、多くのチームを壊した1つです。Strapiは50以上の破壊的な変更を文書化しました。実際には、中程度の複雑さのプロジェクトでマイグレーションに40時間以上の開発者時間がかかるのを見てきました。これはマイナーバージョンバンプではありません――それはあなたのコンテンツレイヤーの書き換えです。

次のメジャーバージョンが半分のカスタムコントローラーを壊すことを知っているため、次のメジャーバージョンを恐れているなら、あなたはツールを超えています。

2. あなたの開発者がフレームワークと戦っている

Strapiの Content-Type Builderは非技術的なユーザーに最適です。TypeScriptに住みたい開発者にとって、コードファースト スキーマの場合、それはボトルネックです。GUIはあなたが編集することを想定していないファイルを生成します。ライフサイクルフックは取り付けられているように感じます。TypeScript サポートはv4の後期に追加され、現在でもネイティブではありません――それは考え直しです。

チームがフレームワークを使ってそれで機能を構築する代わりにフレームワークの周りに回避策を構築し始めるとき、それは明確な信号です。

3. パフォーマンスが問題になっている

Strapiのコールドスタートは通常500msから2000msの範囲です。グローバルレイテンシは積極的なキャッシングなしで200~500msです。ブログの場合は問題ありません。複数の地域のユーザーにサービスを提供するeコマースプラットフォームの場合はそうではありません。

Strapi上で多言語製品カタログを実行していたクライアントがいました。深い関係を持つ約50,000のコンテンツエントリを超えると、API応答時間は2秒のマークを超えました。インデックス作成では修正されませんでした。

4. 支払われたティアの背後にロックされている機能が必要です

Strapiの成長計画は月額45ドルで、3席が含まれています(追加席は1席あたり15ドル)。これはAI機能、ライブプレビュー、コンテンツ履歴のロックを解除します。エンタープライズプライシングはカスタムです。

問題は価格ではありません――それは原則です。ライブプレビューとコンテンツバージョニングなどの機能は、2025年のCMSのテーブルスティックスのように感じます。オープンソースツールのサブスクリプションの背後にゲートされていることは、開発者チームをむしろします。

5. あなたのスタックはStrapiのアーキテクチャを超えて進化しました

Next.js、Vercel、TypeScriptに全力で行った場合、Strapiは不器用な付属肢のように感じ始めます。それは別のNode.jsサービスとして実行されます。つまり、別のデプロイメント、別のモニタリング、別のスケーリングの懸念があります。フロントエンドチームはVercelに数秒で展開し、CMSは独自のインフラストラクチャが必要です。

6. カスタム拡張機能は手術のようになります

条件付きフィールドロジックを追加したいですか?ネストされた繰り返し可能なブロック(検証付き)?カスタム管理パネルコンポーネント?Strapiでは、これらのそれぞれが可能ですが、苦痛です。管理パネルはReactアプリですが、それを拡張することは、通常のReact開発のようには感じない独自の拡張システムをナビゲートすることを意味します。

When You've Outgrown Strapi CMS: Building with Payload + Supabase - architecture

選択肢の理解:Payload vs Supabase vs 現状維持

さらに進む前に、これらのツールが実際に何であるかを明確にしましょう。私はそれらが絶えず混同されているのを見ています。

ツール 実際に何であるか 最適 素晴らしくない
Strapi 管理GUIを備えたオープンソースヘッドレスCMS コンテンツエディター、高速API生成 コードファースト チーム、高性能アプリ
Payload CMS Next.js内で実行されるコードファースト CMSフレームワーク TypeScript開発者、カスタムコンテンツアプリ 非技術的なソロオペレーター
Supabase オープンソースバックエンドプラットフォーム(DB、認証、ストレージ、リアルタイム) アプリケーションデータ、認証、ファイルストレージ コンテンツ編集ワークフロー
Directus 自動生成APIを備えたSQL優先ヘッドレスCMS 既存のデータベースを持つチーム 深いNext.js統合
Sanity リアルタイムコラボレーション付きマネージドヘッドレスCMS 編集チーム、構造化コンテンツ 予算意識の強い自己ホスター

PayloadとSupabaseは競争相手ではありません――それらは相補的です。Payloadはコンテンツモデリング、管理UI、およびコンテンツAPIを処理します。Supabaseはデータベースホスティング、認証、ファイルストレージ、およびリアルタイムサブスクリプションを処理します。一緒に、彼らはStrapiに取って代わり、その後です。

なぜPayload CMSが自然な次のステップなのか

Payload は2025年を通じて2026年に深刻な波を起こしています。MG Softwareはそれを TypeScript/Next.js統合の「市場破壊者」と呼んでいます。そして、私はそれが正確だと思います。

基本的なアーキテクチャの違いは以下の通りです:PayloadはあなたのNext.jsアプリケーション内で実行されます。その横ではなく。別のサービスとしてではなく。内側。あなたのCMSとあなたのフロントエンドは同じデプロイメント、同じTypeScriptタイプ、同じビルドプロセスを共有します。

コードファーストスキーマ定義

GUIをクリックしてコンテンツタイプを作成する代わりに、TypeScriptを書きます:

import { CollectionConfig } from 'payload';

export const Products: CollectionConfig = {
  slug: 'products',
  admin: {
    useAsTitle: 'name',
    defaultColumns: ['name', 'price', 'status'],
  },
  access: {
    read: () => true,
    create: ({ req: { user } }) => user?.role === 'admin',
  },
  fields: [
    {
      name: 'name',
      type: 'text',
      required: true,
    },
    {
      name: 'price',
      type: 'number',
      min: 0,
    },
    {
      name: 'description',
      type: 'richText',
    },
    {
      name: 'category',
      type: 'relationship',
      relationTo: 'categories',
      hasMany: false,
    },
    {
      name: 'variants',
      type: 'array',
      fields: [
        { name: 'sku', type: 'text', required: true },
        { name: 'color', type: 'select', options: ['red', 'blue', 'green'] },
        {
          name: 'stock',
          type: 'number',
          admin: {
            condition: (data, siblingData) => siblingData?.sku !== undefined,
          },
        },
      ],
    },
  ],
  hooks: {
    afterChange: [
      async ({ doc, operation }) => {
        if (operation === 'update' && doc.stock === 0) {
          // Trigger restock notification
        }
      },
    ],
  },
};

これは条件付きフィールドロジック、ネストされた配列、関係フィールド、ロールベースのアクセス制御、およびライフサイクルフックを備えた実際のコンテンツタイプです。すべて1つのファイル。すべてタイプセーフ。すべてGitでバージョン管理されています。

3つの異なるファイルに触れ、管理拡張システムに触れることなくStrapiでそれをやってみてください。

3つのAPIレイヤー

PayloadはスキーマからREST APIとGraphQL APIを自動生成します。しかし、キラー機能はローカルAPIです――ゼロHTTPオーバーヘッドでサーバー側のコードから直接データベースクエリします:

// Inside a Next.js Server Component
import { getPayload } from 'payload';
import config from '@payload-config';

export default async function ProductPage({ params }) {
  const payload = await getPayload({ config });
  
  const product = await payload.findByID({
    collection: 'products',
    id: params.id,
    depth: 2, // Populate relationships 2 levels deep
  });
  
  return <ProductDetail product={product} />;
}

フェッチ呼び出しなし。APIルートなし。シリアル化オーバーヘッドなし。これが、Payloadが比較可能なセットアップのコンテンツ取得でStrapiより約7倍速いベンチマークを取得する理由です。

Supabaseはどこに適合するか(そしてどこに適合しないか)

Supabaseはむしろ CMS ではありません。それについて本当にはっきりしたいと思います。PostgreSQL上に構築されたバックエンドプラットフォームです。しかし、Strapiが貧弱に処理し、Payloadがすべて処理しない複数の問題を解決します。

Supabaseがスタックに何をもたらすか

  • マネージドPostgreSQL:PayloadのPostgreSQL アダプターはSupabaseデータベースに直接接続します。接続プーリング、自動バックアップ、直接SQLクエリのダッシュボードが得られます。Proプランは月額25ドルで始まり、使用量に応じてスケーリングされます。
  • 認証:Supabase Auth は、メール/パスワード、マジックリンク、OAuth プロバイダー、および行レベルセキュリティをサポートしています。アプリにCMS管理者を超えるユーザー向け機能がある場合は、これは大きいです。
  • ファイルストレージ:S3互換のオブジェクトストレージとCDN。Payloadはメディアアップロードを処理できますが、Supabase Storageはアプリケーションファイル、ユーザーアップロード、およびCMS外の何かを処理します。
  • リアルタイムサブスクリプション:PostgreSQLのLISTEN/NOTIFYがクリーンなWebSocket APIでラップされています。Payloadのライブプレビューでこれをペアにしてください。リアルタイムコンテンツ編集エクスペリエンス。
  • エッジ機能:Denoベースのサーバーレス機能(webhookハンドラー、バックグラウンドジョブ、統合用)。

Supabaseがやらないこと

コンテンツエディター向けの管理パネルは提供されません。リッチテキストフィールドとメディア管理を備えたコンテンツAPIは生成されません。コンテンツローカライゼーションやバージョン履歴は処理されません。それはPayloadの仕事です。

Payload + Supabaseスタック:アーキテクチャ深掘り

Strapiから移行するチーム向けにこれをセットアップする方法は次の通りです。これは、コンテンツ管理がコア要件であるNext.js開発プロジェクトに対して、通常推奨するアーキテクチャです。

プロジェクト構造

├── src/
│   ├── app/                    # Next.js App Router
│   │   ├── (frontend)/         # Public-facing pages
│   │   └── (payload)/          # CMS admin routes (auto-generated)
│   ├── collections/            # Payload collection configs
│   │   ├── Posts.ts
│   │   ├── Products.ts
│   │   └── Users.ts
│   ├── globals/                # Payload global configs
│   │   └── SiteSettings.ts
│   ├── lib/
│   │   └── supabase.ts         # Supabase client initialization
│   └── payload.config.ts       # Main Payload config
├── supabase/
│   └── migrations/             # Supabase DB migrations
├── .env.local
└── package.json

PayloadをSupabase PostgreSQLに接続する

// payload.config.ts
import { buildConfig } from 'payload';
import { postgresAdapter } from '@payloadcms/db-postgres';
import { lexicalEditor } from '@payloadcms/richtext-lexical';
import { Posts } from './collections/Posts';
import { Products } from './collections/Products';

export default buildConfig({
  db: postgresAdapter({
    pool: {
      connectionString: process.env.SUPABASE_DB_URL,
      // Use Supabase's connection pooler for serverless
      max: 10,
    },
  }),
  editor: lexicalEditor(),
  collections: [Posts, Products],
  secret: process.env.PAYLOAD_SECRET,
  typescript: {
    outputFile: path.resolve(__dirname, 'payload-types.ts'),
  },
});

重要な注記:Vercelなどのサーバーレス環境にデプロイする場合は、直接接続URLではなくSupabaseの接続プーラーURL(ポート6543)を使用します。直接接続はローカル開発に問題なく機能します。

アプリケーションユーザーのSupabase認証を追加する

Payloadはcms管理者認証を処理します。Supabaseはそれ以外のすべてを処理します:

// lib/supabase.ts
import { createClient } from '@supabase/supabase-js';

export const supabase = createClient(
  process.env.NEXT_PUBLIC_SUPABASE_URL!,
  process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!
);

// In a Server Component or API route
import { createServerClient } from '@supabase/ssr';
import { cookies } from 'next/headers';

export async function getServerSupabase() {
  const cookieStore = await cookies();
  return createServerClient(
    process.env.NEXT_PUBLIC_SUPABASE_URL!,
    process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY!,
    {
      cookies: {
        getAll() {
          return cookieStore.getAll();
        },
        setAll(cookiesToSet) {
          cookiesToSet.forEach(({ name, value, options }) =>
            cookieStore.set(name, value, options)
          );
        },
      },
    }
  );
}

この分離はクリーンです:Payloadはコンテンツを所有しています。Supabaseはアプリケーションデータとユーザーアイデンティティを所有しています。彼らは同じPostgreSQLインスタンスを共有しますが、それぞれのレーンにとどまります。

マイグレーション戦略:Strapiから移動する際に狂わないために

私はこれを砂糖にコートは したくありません――マイグレーションは仕事をかかります。しかし、Strapiコントローラーを尊重し、既存の精神モデルを尊重するシステムに移行しているため、Strapi v4からv5へのアップグレードよりもはるかに痛みが少なくなっています。

ステップバイステップのアプローチ

  1. Strapiコンテンツタイプを監査します。 Content-Type Builderからそれらを JSON としてエクスポートします。それぞれをPayload コレクション設定にマップします。
  2. 新しいNext.jsプロジェクトでPayloadをセットアップします。 npx create-payload-app@latest を実行し、PostgreSQL アダプターを選択します。
  3. PayloadをあなたのSupabaseデータベースに指します。 新しいSupabaseプロジェクトを作成し、接続文字列をつかんで、アダプターを設定します。
  4. TypeScriptでスキーマを再作成します。 これは大部分の作業です。各StrapiコンテンツタイプはPayloadコレクションになります。フィールドはほぼ1対1でマップします――テキスト、数値、リッチテキスト、関係、メディア。
  5. Strapiからデータをエクスポートします。 PostgreSQLにあった場合は pg_dump を使用するか、Strapi REST APIに対してスクリプトを記述してすべてのコンテンツを取得します。
  6. Payloadにインポートします。 シードスクリプトでPayloadのローカルAPIを使用してコンテンツを一括作成します。
  7. あなたのフロントエンドを更新してください。 Strapi API呼び出しをPayload ローカルAPI呼び出し(サーバーコンポーネント内)またはREST/GraphQL呼び出し(クライアントコンポーネント内)に交換します。
  8. デプロイします。 PayloadはNext.js内で実行されるため、2つのアプリケーションではなく1つのアプリケーションをデプロイします。

複雑なマイグレーションの場合、私たちのヘッドレスCMS開発チームは移行を計画するのに役立つことができます。私たちはこれをするのに十分な回数をして、地雷がどこにあるかを知っています。

パフォーマンスベンチマークと実世界のデータ

ここは重要な数値です。2025年に公開されたベンチマークと私たち自身のテストから収集されたものです:

メトリック Strapi v5 Payload 3.x Payload + Supabase
コールド開始時間 500-2000ms 100-300ms 150-350ms
シンプルなクエリ(単一アイテム) 45-80ms 8-15ms 10-20ms
複雑なクエリ(入力済み、3レベル) 200-500ms 30-80ms 40-100ms
管理パネルの読み込み 2-4s 1-2s 1-2s
ビルド時間(500ページ、ISR) N/A(別個) 45-90s 50-100s
グローバルレイテンシ(CDMなし) 200-500ms 50-150ms 60-160ms

Supabaseコネクションプーラーは、直接PostgreSQL接続と比較して小さなオーバーヘッドを追加します。通常、5~15msです。実際には無視できます。

1つの注意:Payloadの設定されたフィールドクエリ(深い関係解決)は、生のデータベースクエリより遅いとしてフラグが付けられています――GitHub issue #11325によると、直接Mongoose/Drizzleコールより約15倍遅いです。読み取り集約的なページの場合、Next.js ISRを使用するか、設定結果をキャッシュすることをお勧めします。すべてのリクエストでデータベースをヒットする代わりに。

このスタックが正しい選択ではない場合

あなたが Payload + Supabase が大すぎるか単に間違った場合のシナリオに言及しない場合、私はあなたを不利にしています。

  • あなたのチームはTypeScriptを書きません。 Payloadはコードファーストです。コンテンツチームがすべてを管理し、CMSを維持している開発者がいない場合、Strapiのグラフィカルユーザーインターフェイスは本当に良いです。またはSanityまたはContentfulを見てください。
  • 今日大規模なプラグインエコシステムが必要です。 Payloadのエコシステムは成長していますが、Strapiの100以上の拡張機能より小さいです。Supabaseの特定の統合が存在するがPayloadには存在しない場合は、ビルド時間を考慮してください。
  • シンプルなブログやマーケティングサイトを構築しています。 Strapiはこれでうまく機能します。だからそうするAstroとのヘッドレスサイト。それを過度に設計しないでください。
  • エッジファースト性能が必要です。 サブ50msのグローバルレイテンシがハード要件の場合は、Cloudflare Workersの SonicJS を調べてください。Payloadはnode.jsで実行されます――それは速いですが、エッジネイティブではありません。

このマイグレーションが特定のプロジェクトに対して理にかなっているかについて話し合いたいですか?私たちに連絡してください――営業ピッチではなく、正直な評価をあなたに与えます。

よくある質問

Payload CMSは本当に無料ですか? はい。Payloadはmitライセンスであり、機能制限なしで自己ホストするのは無料です。Payload Cloudホスティングサービスはインフラストラクチャを管理したくないチーム向けのオプションですが、すべてのCMS機能――ライブプレビュー、アクセス制御、ローカライゼーション、バージョニング――はオープンソースバージョンで利用可能です。ライブプレビューとコンテンツ履歴を月額45ドルの成長計画の背後にゲートするStrapiと比較してください。

SupabaseをCMS自体として使用できますか? 技術的には、Supabaseの自動生成されたAPIと行レベルセキュリティを使用してコンテンツ管理インターフェイスをSupabase上に構築できます。しかし、Payloadがすぐに提供するものを再構築しています:管理パネル、リッチテキスト編集、メディア管理、コンテンツバージョニング、およびアクセス制御。Supabaseはバックエンドプラットフォームであり、CMSではありません。それが得意なことのために使用してください――データベースホスティング、認証、ストレージ――そして、コンテンツレイヤーをPayloadに処理させてください。

Strapiから Payloadへのマイグレーションにはどのくらい時間がかかりますか? 10~20のコンテンツタイプと数千のエントリを持つ典型的なプロジェクトの場合は、2~4週間の開発者時間を予想します。スキーマ再作成が最大の部分です――Strapiコンテンツタイプの翻訳。Payloadはtypescriptコンフィグです。データマイグレーションは通常、優れたスクリプトを使用して1~2日です。フロントエンドの更新は、コードがStrapiのAPI応答形式にどの程度厳密に結合されているかに応じて異なります。データアクセスレイヤーまたは抽象化を使用したチームは、より簡単な時間を過ごします。

Payloadは PostgreSQL以外のデータベースで機能しますか? Payloadは、公式のデータベースアダプターを通じてMongoDBとPostgreSQLの両方をサポートしています。この記事で説明するSupabaseスタックの場合、PostgreSQL アダプターを使用します。mongodbバックグラウンドから来ている場合、Payloadの MongoDB アダプターは実際にはより成熟しています。mongodbはPayloadの元のデータベースだったため。2025年では両方が本番対応です。

Directusは、Strapiの代わりとしてどうですか? Directusは、特にCMSインターフェイスを通じて公開したい既存のSQLデータベースがある場合、堅実なオプションです。データベーススキーマから管理パネルとAPIを自動生成します。これは賢明です。Payloadと比較した主な欠点は、深いNext.js統合がないことです――Directusはstrapiと同様に別のサービスとして実行されます。あなたのチームがNext.js/Vercelスタックにいない場合、Directusは真剣に考慮する価値があります。

Payload + Supabaseを Vercel にデプロイできますか? 絶対に――これは実際に理想的なデプロイメントターゲットです。PayloadはあなたのNext.jsアプリ内で実行されるため、Vercelへの展開はあなたのGitリポジトリへのプッシュと同じくらい簡単です。Supabaseはマネージドサービスとして実行されるため、その側に展開するものはありません。あなたの総インフラストラクチャは以下のようになります:Compute and CDNの場合のVercel、データベースと認証の場合のSupabase。2つのサービス、1つのデプロイメント パイプライン。私たちは頻繁にクライアント向けにこれをセットアップしていますNext.js開発慣例

Payloadのadminパネルはカスタマイズ可能ですか? とても。管理UIはReactで構築されており、カスタムコンポーネント、カスタムビュー、およびカスタムフィールドをサポートします。ダッシュボードウィジェット、カスタムナビゲーション項目を追加でき、デフォルトのUI要素をオーバーライドできます。Payload 3.x以降は、管理のカスタマイズはReactサーバーコンポーネントを使用します。これは、カスタム管理コードがAPI呼び出しなしでサーバー側でデータをフェッチできることを意味します。これは、メジェクトして パッチを適用する必要があるStrapiの管理拡張システムとは異なる世界です。

このスタックを本番環境で実行するのにはどのくらいの費用がかかりますか? 小~中規模のプロジェクトの場合:月額20ドルのVercel Pro + 月額25ドルのSupabase Pro = 月額45ドルの合計。これにより、サーバーレスコンピュート、8GBストレージ搭載のマネージドPostgreSQLデータベース、250MBのファイルストレージ、50,000月間アクティブユーザーの認証、および自動バックアップが得られます。そこから必要に応じてスケーリングします。Strapiを自己ホストすることと比較(VPS月額20~50ドル)+ 独自のデータベース管理、またはStrapi CloudのGrowth プランは月額45ドルで、シート数が限定されています。Payload + Supabaseの組み合わせは費用的に競争力があり、操作ははるかに簡単です。詳細なプロジェクト見積もりについては、価格ページを確認してください。