mcpField
B
backend-patterns

backend-patterns

github.com/kensaurus開発938 回インストール2 週間前に更新
リポジトリ

backend-patterns について

backend-patternsは、既存の構成を踏まえてサーバー側の設計パターンを選び実装するためのスキルです。リクエスト処理、データベース、キャッシュ、バックグラウンドジョブ、分散システムを扱い、検証と安全性を重視します。

主な機能

  1. 01既存アーキテクチャと実装の事前確認
  2. 02Server ActionsとtRPCのパターン
  3. 03データベース、キャッシュ、バックグラウンドジョブ
  4. 04レート制限と分散システムのパターン
  5. 05認証、入力、エラー、冪等性の検証

活用シーン

  1. 01Next.js Server Actionsの安全な書き込みフロー設計
  2. 02注文処理などの再試行可能な副作用のジョブ化
  3. 03データベースでの同時更新や論理削除への対応
  4. 04重要なエンドポイントへのレート制限と入力検証の追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/kensaurus/skills --skill backend-patterns

インストール後、Claude Code で/backend-patternsを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
architecture-patterns.md
data-and-jobs.md
request-patterns.md

詳細

バックエンドパターンのスキル

自由度:混在。 適用するパターンの選択は[自由度:高]。 既存アーキテクチャの調査と検証リストは[自由度:低 — 必ずそのまま実行]です。

考え方

  1. 観察 — 既存のサーバー/API/アクション、ORM、キュー、キャッシュを確認します
  2. 解釈 — パターンが不足しているのか、重複しているのか、レイヤーが間違っているのかを判断します
  3. 分類 — 再利用/キューの追加/キャッシュの追加/レート制限の追加/エッジ関数
  4. 重大度 — 未認証の変更は、キャッシュ不足よりも優先度が高くなります

作業例

観察: createOrder がメールをインラインで送信しています。Inngest/キューはなく、チェックアウトの p95 は 4 秒です。 解釈: 確認処理はリクエスト後の作業であり、リクエスト処理経路には含めません。 分類: after() または order/created ジョブを使います。書き込みはトランザクション内に保ちます。 検証: 注文の行がコミットされること、メール/在庫処理がレスポンス後に実行されること、再試行で二重請求が発生しないことを確認します。

報告前の自己批評

  • 既存のものを優先 — 2つ目のパターンを追加する前に、server/api/actions を検索しました
  • 認証 + 検証 — すべての変更処理でセッションと Zod を確認します
  • 冪等性 — 新しい経路で再試行しても、処理が二重に適用されません
  • 適切な担当者 — どのアーキテクチャを選ぶか → audit-backend-architecture

最新のパターンとベストプラクティスを使って、スケーラブルで保守しやすいバックエンドアーキテクチャを設計します。

コード例は Next.js App Router + Supabase/Prisma を中心にしています。パターンは スタックに依存しないため、検出されたエコシステムに合わせて ORM、クライアントライブラリ、デプロイ先を 調整してください。

まず既存のものを確認する [自由度:低 — 必ずそのまま実行]

バックエンドパターンを実装する前に、必ず次の項目を確認してください。

  1. 既存のアーキテクチャを確認する:
ls -la src/server/ src/api/ app/api/ supabase/functions/ 2>/dev/null
cat package.json | grep -i "prisma\|drizzle\|supabase\|trpc"
  1. 既存のパターンを確認する:
rg "createTRPCRouter|publicProcedure" --type ts -l
rg "'use server'" --type ts -l
ls -la supabase/migrations/*.sql 2>/dev/null | tail -5
  1. データベースの設定を確認する:
cat prisma/schema.prisma 2>/dev/null | head -50
cat supabase/config.toml 2>/dev/null

理由: バックエンドの変更は広範囲に影響します。まず既存のアーキテクチャを把握してください。

Server Actions(Next.js 16 以降) [自由度:高]

Next.js 16:Turbopack がデフォルト、'use cache' + cacheComponents、reactCompiler: true、middleware.ts → proxy.ts(両方を grep してください)。即時ナビゲーションには enhance-web-instant-nav を使用します。

  • すべてのアクション内の順序:認証チェック → Zod safeParse → 実行 → 既知のエラー(Prisma P2002)をマッピング → 汎用エラーメッセージ。
  • ActionResult<T> を返します:{ success: true, data } または { success: false, error, fieldErrors? }。クライアントに例外をスローしないでください。
  • 書き込みの成功後に revalidatePath を実行します。
  • レスポンス後の処理(確認メール、在庫、通知)は、next/server の after() に渡し、書き込みをトランザクション内に保ちます。
'use server'
import { after } from 'next/server'

export async function createOrder(formData: FormData) {
  const order = await db.order.create({ data: { /* ... */ } })
  after(async () => {                      // runs after the response is sent
    await sendOrderConfirmation(order.id)
    await updateInventory(order.items)
  })
  revalidatePath('/orders')
  return { success: true, data: order }
}

完全な createUser アクションと after() の例:references/request-patterns.md §Server Actions。

tRPC の設定 [自由度:高]

  • 誰でも実行できる読み取りには publicProcedure を使い、ctx.session を使う処理には protectedProcedure を使います。
  • すべてのプロシージャに Zod .input() を設定します。ミューテーションでは入力ではなく、セッションから createdById を設定します。
  • リストエンドポイントはカーソルでページネーションします。limit + 1 件を取得し、余分な行を取り除いて nextCursor とします。

完全な usersRouter(getById、create、カーソルページネーション付きの list):references/request-patterns.md §tRPC router definition。

Supabase Edge Functions [自由度:高]

  • Deno.serve を使い、まず CORS ヘッダーを付けて OPTIONS に応答します。
  • JSON の解析前に、生のボディに対する Webhook 署名を検証します。一致しない場合は 401 を返します。
  • SUPABASE_SERVICE_ROLE_KEY から作成した管理者クライアントは RLS をバイパスします。関数内でのみ使用してください。
  • すべてのエラーを捕捉し、サーバー側でログに記録して、CORS ヘッダー付きの汎用 500 JSON ボディを返します。

完全な process-webhook 関数:references/request-patterns.md §Supabase Edge Function。

データベースパターン [HIGH freedom]

  • 楽観的ロック — version INT 列を使用します。UPDATE ... WHERE id = $1 AND version = $2 を実行し、更新された行が 0 件の場合は、同時更新として扱います。
  • 論理削除 — インデックスを付けた NULL 許容の deletedAt を使用します。すべての読み取りで deletedAt: null に絞り込み、削除時にタイムスタンプを設定します。
  • 監査ログ — SECURITY DEFINER トリガーを使い、TG_OP、row_to_json、auth.uid() によって audit_logs(table_name, record_id, action, old_data, new_data, user_id) にデータを記録します。
UPDATE orders SET status = 'shipped', version = version + 1
WHERE id = $1 AND version = $2;   -- 0 rows → concurrent update, retry or surface conflict

Prisma の論理削除モデルと完全な監査トリガー:references/data-and-jobs.md §論理削除、§監査ログ。

キャッシュパターン [HIGH freedom]

  • Next.js:fetch(url, { next: { revalidate, tags } }) を使用し、必要に応じて revalidateTag を呼び出します。タグ付きで DB クエリを unstable_cache で囲みます。
  • Redis(Upstash):getCachedData(key, fetcher, ttl) ヘルパーを 1 つ用意し、キャッシュアサイド方式を使います。エンティティと ID をキーにします(user:${id})。
  • 古さの許容範囲に応じて TTL を決め、書き込み時にキャッシュを無効化できるよう、常にタグを付けます。
const getCachedUser = unstable_cache(
  async (id: string) => db.user.findUnique({ where: { id } }),
  ['user'],
  { revalidate: 3600, tags: ['users'] }
)

Next.js のキャッシュ呼び出しと Redis ヘルパー:references/data-and-jobs.md §Next.js キャッシュ、§Redis キャッシュ。

バックグラウンドジョブ [HIGH freedom]

  • デフォルトは Inngest です。inngest.createFunction({ id }, { event }, async ({ event, step }) => ...) を使い、副作用はそれぞれ独立した step.run にまとめます。これにより、再試行時に最初からやり直さず、途中から再開できます。
  • 書き込みのコミット後、Server Action から inngest.send({ name: 'order/created', data }) を呼び出してトリガーします。
  • 在庫切れなどによる早期終了は、例外をスローするのではなく、step.run と return { status: 'cancelled' } で処理します。
export const processOrder = inngest.createFunction(
  { id: 'process-order' }, { event: 'order/created' },
  async ({ event, step }) => {
    const payment = await step.run('charge-payment', () => chargeCustomer(event.data.paymentMethod))
    await step.run('send-confirmation', () => sendOrderConfirmation(event.data.orderId))
    return { status: 'completed', paymentId: payment.id }
  }
)

Inngest 関数の完全な例と Trigger.dev によるスケジュールタスクの代替案:references/data-and-jobs.md §バックグラウンドジョブ、§代替案。

レート制限 [HIGH freedom]

  • Redis.fromEnv() を使い、@upstash/ratelimit と Ratelimit.slidingWindow(10, '10 s') を組み合わせます。
  • ユーザー ID(匿名の場合は IP)をキーにします。!success の場合は、reset の値から算出した retryAfter 秒とともに Too many requests を返します。

rateLimitedAction の完全な例:references/request-patterns.md §レート制限。

アーキテクチャパターン(分散システム) [HIGH freedom]

ゲートウェイ、BFF、バルクヘッド、サーキットブレーカー、アウトボックス+CDC、サーガ、ヘキサゴナルアーキテクチャ、ACL、ストラングラーフィグについては → references/architecture-patterns.md。トポロジーに合ったパターンを選びます (モノリスにメッシュは不要です。読み取りと書き込みに違いがない限り、CQRS も不要です)。タイムアウト/再試行/冪等性 → audit-resilience。構造的なギャップのレポート → audit-backend-architecture。

検証 [LOW freedom — do not skip]

バックエンドパターンの実装後に、次の項目を確認します。

  1. エラー処理 → すべてのエラーを捕捉してログに記録し、安全なレスポンスを返す
  2. 認証チェック → すべての変更処理で認証を検証する
  3. 入力検証 → すべての入力に Zod スキーマを適用する
  4. レート制限 → 機密性の高いエンドポイントを保護する
  5. 冪等性 → 重要な処理で再試行に対応する
  6. ログ記録 → 機密データを含まない構造化ログを使用する
  7. テスト → ビジネスロジックにはユニットテスト、API には統合テストを実施する

コメント