CLAUDE LABEN
FORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられていますFORK — Claude Code 2.1.212で/forkの挙動が変わりました。会話を新しいバックグラウンドセッションへ複製し、作業を続けたまま並走できます。従来のセッション内サブエージェントは/subtaskに移りましたLIMITS — WebSearchの呼び出しがセッション単位で既定200回に制限されました。サブエージェントの起動も既定200回が上限で、暴走した検索・委譲のループを止められますMCPBG — 2分を超えるMCPツール呼び出しは自動的にバックグラウンドへ移り、セッションが固まらなくなりました。しきい値はCLAUDE_CODE_MCP_AUTO_BACKGROUND_MSで調整できますPLANFIX — プランモードがtouchやrmといったファイルを変更するBashコマンドを、許可プロンプトもcanUseToolコールバックも通さずに実行してしまう不具合が修正されましたSONNET5 — Claude Sonnet 5は導入価格として入力100万トークンあたり2ドル、出力10ドルで提供中です。8月31日を過ぎると3ドルと15ドルに戻りますIPO — Anthropicが早ければ10月の株式公開を視野に、引受銀行が投資家との面談を組み始めたと報じられています
記事一覧/API & SDK
API & SDK/2026-04-28上級

Claude API × Stripe で月額課金 SaaS を設計する — アーキテクチャから実装まで

Claude API を組み込んだ SaaS の月額課金設計を、Stripe Billing・Usage Metering・Webhook の実装コード付きで解説します。APIコスト管理からティア設計まで、個人開発者が実際に収益化するための設計パターンです。

claude-api81stripe6saas2monetization4billing6webhook3usage-meteringarchitecture7

Claude API で何かを作った。動いた。ユーザーも増えた。でも、これをどう課金すればいいのか……。

僕自身も個人開発の中でこの問題に直面してきました。API の利用は課金・請求と切り離せません。単なる決済ボタンではなく、実際にユーザーごとの API 利用量をトラッキングし、そのコストを回収できる設計が必要です。

Claude API のコスト構造を理解する

Stripe で料金を決める前に、Claude API の実際のコストを把握する必要があります。

Claude の価格設定は単純です。入力トークンと出力トークンで単価が異なり、モデル(Opus / Sonnet / Haiku)で変わります。2026年時点での概算は以下の通りです。

モデル入力出力
Haiku$0.80/M$4/M
Sonnet$3/M$15/M
Opus$15/M$75/M

(M = 100万トークン、数値は概算)

ここで重要なのは、入力と出力のコスト比です。Opus なら出力は入力の5倍高い。つまり、長めの応答を大量に返すアプリケーションでは、単に「リクエスト数」を課金単位にすると大赤字になります。

実例

Chat とコード生成を組み合わせた SaaS を想定します。

  • ユーザーが「この API 使い方教えて」と 100 トークンの質問を送信
  • Claude が 500 トークンの詳細な回答を返す
  • コスト(Sonnet) = (100 × $3 + 500 × $15) / 1,000,000 ≈ $0.0081

月 1,000 リクエストなら約 $8 です。一方、ユーザーから「月額 $5」を取っていたら、半年で赤字確定です。

これが、多くの個人開発者が AI SaaS で失敗する原因の一つです。

損益分岐点の計算式

SaaS の各ティアで、「月額 X 円」に対して「月額 Y 円のコストで採算が取れるか」を事前に計算しておきます。

// 月額課金と API コストの関係を計算
const calculateBreakEven = (
  monthlyPrice,
  avgInputTokens,
  avgOutputTokens,
  estimatedRequestsPerMonth,
  model = 'sonnet'
) => {
  const pricing = {
    haiku: { input: 0.8, output: 4 },
    sonnet: { input: 3, output: 15 },
    opus: { input: 15, output: 75 }
  };
  
  const rate = pricing[model];
  const costPerRequest = (
    (avgInputTokens * rate.input + avgOutputTokens * rate.output) / 1_000_000
  );
  
  const totalMonthlyCost = costPerRequest * estimatedRequestsPerMonth;
  const profit = monthlyPrice - totalMonthlyCost;
  const margin = (profit / monthlyPrice) * 100;
  
  return {
    costPerRequest: costPerRequest.toFixed(4),
    totalMonthlyCost: totalMonthlyCost.toFixed(2),
    monthlyProfit: profit.toFixed(2),
    profitMargin: margin.toFixed(1)
  };
};
 
// Pro プランの採算性をチェック
const breakEven = calculateBreakEven(
  9.99,           // 月額 $9.99
  250,            // 平均入力トークン
  800,            // 平均出力トークン
  500,            // 月間リクエスト数予想
  'sonnet'
);
 
console.log(breakEven);
// {
//   costPerRequest: '0.0129',
//   totalMonthlyCost: '6.45',
//   monthlyProfit: '3.54',
//   profitMargin: '35.4'
// }

この計算で大事なのは、使用パターンの想定が外れた時の余裕度です。「利益率 35%」と見えますが、実際には:

  • ユーザーが予想より多くリクエストを送る
  • より長い応答が必要なリクエストが増える
  • Opus へのアップグレード要望が増える

……といった時に、すぐに赤字に転じます。個人開発では最初、利益率 50% 以上を目安に設定し、データが集まった後に最適化するのが実用的です。

ティア設計の実装パターン

Free / Pro / Enterprise の3層構造が、個人開発の SaaS では最適です。

// lib/billing/tiers.ts
export const BILLING_TIERS = {
  free: {
    name: 'Free',
    monthlyPrice: 0,
    requestLimit: 10,           // 月間リクエスト数
    maxOutputTokens: 500,        // 1リクエストあたりの最大出力
    model: 'haiku',              // 使用モデル制限
    supportEmail: false,
  },
  pro: {
    name: 'Pro',
    monthlyPrice: 9.99,
    requestLimit: 500,
    maxOutputTokens: 4000,
    model: 'sonnet',
    supportEmail: true,
  },
  enterprise: {
    name: 'Enterprise',
    monthlyPrice: null,          // カスタム料金
    requestLimit: Infinity,
    maxOutputTokens: Infinity,
    model: 'opus',
    supportEmail: true,
    features: ['priority-support', 'api-access', 'sso']
  }
} as const;
 
export type BillingTier = keyof typeof BILLING_TIERS;
 
export const getTierConfig = (tier: BillingTier) => BILLING_TIERS[tier];

ここで工夫するべき点は、Free ティアの設計です。

  • 「無料は完全に制限」ではなく、「月10リクエストなら Haiku で十分賄える」という現実的な制限
  • Haiku は Sonnet の 1/5 のコスト。Free ユーザーが月10リクエスト(Haiku)なら、月額コストは約 $0.05 ですみます
  • 十分な体験ができるので、実際に Pro へのコンバージョンが期待できる

逆に「月1リクエストだけ無料」という Free ティアは、試す価値を感じてもらえません。

Claude API トークン消費のリアルタイムトラッキング

月額課金と使用量ベース課金を組み合わせるには、ユーザーごとの API 消費を正確に記録する必要があります。

Stripe では「Usage Records」という機能で、毎月の消費量を後から報告できます。ただし、これは「月末に集計して報告」するやり方。リアルタイムで表示したい場合は、自分たちで追跡テーブルを持つのが実装の基本です。

// lib/db/usage.ts
import { Database } from '@your-db/client';
 
export interface UsageRecord {
  userId: string;
  timestamp: Date;
  inputTokens: number;
  outputTokens: number;
  model: 'haiku' | 'sonnet' | 'opus';
  requestId: string;
  cost: number; // USD
}
 
// Anthropic SDK から token_usage を抽出して記録
export const recordTokenUsage = async (
  db: Database,
  userId: string,
  response: Message,
  model: string
) => {
  const inputTokens = response.usage.input_tokens;
  const outputTokens = response.usage.output_tokens;
  
  // トークン数からドルコストを計算
  const costUSD = calculateTokenCost(model, inputTokens, outputTokens);
  
  await db.usage.create({
    userId,
    timestamp: new Date(),
    inputTokens,
    outputTokens,
    model,
    requestId: response.id,
    cost: costUSD,
  });
};
 
const calculateTokenCost = (
  model: string,
  inputTokens: number,
  outputTokens: number
): number => {
  const rates: Record<string, { input: number; output: number }> = {
    'claude-3-5-haiku-latest': { input: 0.8, output: 4 },
    'claude-3-5-sonnet-latest': { input: 3, output: 15 },
    'claude-opus-4-1': { input: 15, output: 75 },
  };
  
  const rate = rates[model] || rates['claude-3-5-sonnet-latest'];
  return (inputTokens * rate.input + outputTokens * rate.output) / 1_000_000;
};
 
// ユーザーの月間集計を取得
export const getMonthlySummary = async (
  db: Database,
  userId: string,
  year: number,
  month: number
) => {
  const startDate = new Date(year, month - 1, 1);
  const endDate = new Date(year, month, 1);
  
  const records = await db.usage.findMany({
    where: {
      userId,
      timestamp: {
        gte: startDate,
        lt: endDate,
      },
    },
  });
  
  return {
    totalRequests: records.length,
    totalInputTokens: records.reduce((sum, r) => sum + r.inputTokens, 0),
    totalOutputTokens: records.reduce((sum, r) => sum + r.outputTokens, 0),
    totalCost: records.reduce((sum, r) => sum + r.cost, 0),
    models: [...new Set(records.map(r => r.model))],
  };
};

このテーブルに対して、Stripe Usage Metering へ「月1回、月末に集計値を送信」というバッチ処理を組みます。

// jobs/sync-usage-to-stripe.ts
import { stripe } from '@/lib/stripe';
import { db } from '@/lib/db';
 
export const syncUsageToStripe = async () => {
  // 全ユーザーの当月分を集計
  const now = new Date();
  const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
  const endOfMonth = new Date(now.getFullYear(), now.getMonth() + 1, 1);
  
  // 有効なサブスクリプションを持つユーザーを取得
  const subscriptions = await db.subscription.findMany({
    where: {
      status: 'active',
      tier: { in: ['pro', 'enterprise'] }, // Free は課金対象外
    },
    include: { user: true },
  });
  
  for (const sub of subscriptions) {
    const usage = await db.usage.aggregate({
      where: {
        userId: sub.userId,
        timestamp: { gte: startOfMonth, lt: endOfMonth },
      },
      _sum: { cost: true },
    });
    
    const costInCents = Math.round((usage._sum.cost || 0) * 100);
    
    // Stripe に使用量を報告
    await stripe.billing.meterEvents.create({
      event_name: 'api_usage',
      payload: {
        value: costInCents,
        stripe_customer_id: sub.stripeCustomerId,
      },
    });
  }
};

実装のポイント

  • 小数点の取り扱い: Stripe では金額は「セント単位の整数」で扱います。浮動小数点の丸め誤差に注意
  • タイムゾーン: 「月末集計」は UTC を基準にするか、ユーザーのタイムゾーンを基準にするか、事前に決める(後から変更は混乱のもと)
  • リトライ: バッチ処理が途中で失敗した時は、失敗したユーザーだけ再実行できる仕組みが必須

Stripe Webhook による請求・ダウングレード管理

Stripe でサブスクリプションを作成しただけでは不十分です。実際には:

  • 月末に自動請求が成功したか確認したい
  • 請求失敗時に自動でユーザーをダウングレードしたい
  • 月額の使用量制限をリセットしたい

これらは全て Webhook で実装します。

// app/api/stripe/webhooks/route.ts
import { stripe } from '@/lib/stripe';
import { db } from '@/lib/db';
import { NextRequest } from 'next/server';
 
const webhookSecret = process.env.STRIPE_WEBHOOK_SECRET!;
 
export async function POST(req: NextRequest) {
  const body = await req.text();
  const signature = req.headers.get('stripe-signature')!;
  
  // Webhook の署名検証
  let event;
  try {
    event = stripe.webhooks.constructEvent(body, signature, webhookSecret);
  } catch (err: any) {
    return new Response(`Webhook Error: ${err.message}`, { status: 400 });
  }
  
  // idempotency を確保するため、既処理イベントはスキップ
  const eventExists = await db.webhookEvent.findUnique({
    where: { stripeEventId: event.id },
  });
  
  if (eventExists) {
    return new Response('Event already processed', { status: 200 });
  }
  
  // イベントを記録(リプレイ攻撃対策)
  await db.webhookEvent.create({
    data: {
      stripeEventId: event.id,
      type: event.type,
      processedAt: new Date(),
    },
  });
  
  // イベント種別ごとの処理
  switch (event.type) {
    case 'invoice.payment_succeeded': {
      const invoice = event.data.object as any;
      const subscription = await stripe.subscriptions.retrieve(invoice.subscription);
      const customerId = subscription.customer as string;
      
      // 本社サイドのサブスクリプションを「有効」に
      await db.subscription.update({
        where: { stripeCustomerId: customerId },
        data: { status: 'active', failedPaymentCount: 0 },
      });
      break;
    }
    
    case 'invoice.payment_failed': {
      const invoice = event.data.object as any;
      const subscription = await stripe.subscriptions.retrieve(invoice.subscription);
      const customerId = subscription.customer as string;
      
      const sub = await db.subscription.findUnique({
        where: { stripeCustomerId: customerId },
      });
      
      const failureCount = (sub?.failedPaymentCount || 0) + 1;
      
      // 3回連続失敗したらダウングレード
      if (failureCount >= 3) {
        await db.subscription.update({
          where: { stripeCustomerId: customerId },
          data: { tier: 'free', status: 'downgraded' },
        });
        
        // ユーザーにメール送信(通知)
        // await sendEmail({...})
      } else {
        await db.subscription.update({
          where: { stripeCustomerId: customerId },
          data: { failedPaymentCount: failureCount },
        });
      }
      break;
    }
    
    case 'customer.subscription.deleted': {
      const subscription = event.data.object as any;
      const customerId = subscription.customer as string;
      
      await db.subscription.update({
        where: { stripeCustomerId: customerId },
        data: { status: 'cancelled', tier: 'free' },
      });
      break;
    }
    
    case 'billing_portal.session.created': {
      // 顧客がポータルで設定を変更
      // ここではログ記録のみ(特に処理は不要)
      break;
    }
  }
  
  return new Response('OK', { status: 200 });
}

Webhook 実装で重要な3つのポイント

  1. 冪等性(Idempotency)

    • Stripe が同じイベントを複数回送信する可能性がある
    • stripeEventIdwebhookEvent テーブルに記録して、重複処理を防ぐ
    • 最初から「一度だけ処理される」という保証がない設計が正解
  2. エラーハンドリング

    • Webhook の処理中に DB へのアクセスが失敗することがある
    • 失敗した場合は HTTP 500 を返して Stripe に「再試行してくれ」と伝える
    • 成功時は HTTP 200 を返す
  3. タイムアウト

    • Webhook の処理は 30 秒以内に完了させる
    • 重い処理は Queue(Bull など)に push して非同期実行する

Next.js ミドルウェアでのレート制限・機能制限

API エンドポイントを呼ぶ際に、毎回「このユーザーは Pro か」「今月の使用量はあと何か」を確認する必要があります。

// middleware.ts
import { NextRequest, NextResponse } from 'next/server';
import { jwtVerify } from 'jose';
import { db } from '@/lib/db';
 
const secret = new TextEncoder().encode(process.env.JWT_SECRET!);
 
export async function middleware(request: NextRequest) {
  // /api/chat/* へのリクエストに対してのみ
  if (!request.nextUrl.pathname.startsWith('/api/chat')) {
    return NextResponse.next();
  }
  
  // JWT トークンから user ID を取得
  const authHeader = request.headers.get('authorization');
  if (!authHeader?.startsWith('Bearer ')) {
    return new NextResponse('Unauthorized', { status: 401 });
  }
  
  const token = authHeader.slice(7);
  let payload;
  try {
    const verified = await jwtVerify(token, secret);
    payload = verified.payload;
  } catch {
    return new NextResponse('Invalid token', { status: 401 });
  }
  
  const userId = payload.sub as string;
  
  // ユーザーの登録情報と当月使用量を取得
  const user = await db.user.findUnique({
    where: { id: userId },
    include: { subscription: true },
  });
  
  if (!user?.subscription) {
    return new NextResponse('No subscription', { status: 403 });
  }
  
  // 当月の使用量を集計
  const now = new Date();
  const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
  
  const monthlyUsage = await db.usage.aggregate({
    where: {
      userId,
      timestamp: { gte: startOfMonth },
    },
    _count: true,
  });
  
  const tier = BILLING_TIERS[user.subscription.tier];
  const requestCount = monthlyUsage._count;
  
  // リクエスト数制限をチェック
  if (requestCount >= tier.requestLimit) {
    return new NextResponse(
      JSON.stringify({
        error: 'Monthly request limit exceeded',
        limit: tier.requestLimit,
        used: requestCount,
      }),
      { status: 429 }
    );
  }
  
  // リクエスト情報をレスポンスヘッダに追加(ルートハンドラで参照可能)
  const response = NextResponse.next();
  response.headers.set('x-user-id', userId);
  response.headers.set('x-tier', user.subscription.tier);
  response.headers.set('x-requests-remaining', String(tier.requestLimit - requestCount));
  
  return response;
}
 
export const config = {
  matcher: ['/api/chat/:path*'],
};

ルートハンドラ側では、このヘッダ情報を使って Claude API の呼び出しを制御します。

// app/api/chat/route.ts
import { NextRequest, NextResponse } from 'next/server';
import Anthropic from '@anthropic-ai/sdk';
import { recordTokenUsage, getMonthlySummary } from '@/lib/billing/usage';
import { db } from '@/lib/db';
 
const client = new Anthropic();
const BILLING_TIERS = { /* ... */ };
 
export async function POST(request: NextRequest) {
  const userId = request.headers.get('x-user-id')!;
  const tier = request.headers.get('x-tier')! as any;
  const tierConfig = BILLING_TIERS[tier];
  
  const body = await request.json();
  const { messages, model: userRequestedModel } = body;
  
  // ユーザーが Pro 以上でなければ Haiku を強制
  const model = tier === 'free' ? 'claude-3-5-haiku-latest' : userRequestedModel;
  
  try {
    // Claude API に問い合わせ
    const response = await client.messages.create({
      model,
      max_tokens: tierConfig.maxOutputTokens,
      messages,
    });
    
    // 使用量を DB に記録
    await recordTokenUsage(db, userId, response, model);
    
    // クライアントに返す
    return NextResponse.json({
      content: response.content,
      usage: {
        inputTokens: response.usage.input_tokens,
        outputTokens: response.usage.output_tokens,
      },
    });
    
  } catch (error) {
    // API エラーのハンドリング
    if (error instanceof Anthropic.RateLimitError) {
      return NextResponse.json(
        { error: 'Claude API rate limited. Try again later.' },
        { status: 429 }
      );
    }
    throw error;
  }
}

本番環境でのコスト監視とアラート

API SaaS の最大の敵は「予想外のコスト爆発」です。バグ一つで、ボットが大量リクエストを送ってきたら……月間 $10,000 の請求になることもあります。

// jobs/monitor-api-costs.ts
import { db } from '@/lib/db';
import { sendAlert } from '@/lib/email';
 
export const monitorAPICosts = async () => {
  const now = new Date();
  const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1);
  
  // 当月の集計
  const monthlyCost = await db.usage.aggregate({
    where: { timestamp: { gte: startOfMonth } },
    _sum: { cost: true },
  });
  
  const totalCost = monthlyCost._sum.cost || 0;
  const budget = 1000; // 月間予算 $1000
  
  // 予算の 80% に達したらアラート
  if (totalCost > budget * 0.8) {
    await sendAlert({
      to: 'admin@yourapp.com',
      subject: `Cost Alert: ${(totalCost / budget * 100).toFixed(0)}% of monthly budget used`,
      body: `Current API cost: $${totalCost.toFixed(2)} / $${budget}`,
    });
  }
  
  // 1日単位での異常検知
  const yesterday = new Date(now);
  yesterday.setDate(yesterday.getDate() - 1);
  yesterday.setHours(0, 0, 0, 0);
  
  const yesterdayCost = await db.usage.aggregate({
    where: {
      timestamp: {
        gte: yesterday,
        lt: new Date(yesterday.getTime() + 24 * 60 * 60 * 1000),
      },
    },
    _sum: { cost: true },
  });
  
  // 1日のコストが平均の 3 倍なら異常
  const dailyAverage = totalCost / now.getDate(); // 平均日次コスト
  const yesterdayTotal = yesterdayCost._sum.cost || 0;
  
  if (yesterdayTotal > dailyAverage * 3) {
    await sendAlert({
      to: 'admin@yourapp.com',
      subject: `Anomaly: Yesterday's API cost $${yesterdayTotal.toFixed(2)} (avg: $${dailyAverage.toFixed(2)})`,
      body: `Investigate potential bot activity or budget issues.`,
    });
  }
};

このモニタリングを cron ジョブ(またはCloudflare Cron Triggers)で毎日実行します。

Stripe 側の設定と結線

ここまで説明したのは、アプリケーション側の実装です。Stripe のダッシュボード側も設定が必要です。

  1. 商品とプランの作成

    • Free / Pro / Enterprise のプランを Stripe ダッシュボードで作成
    • Pro は「$9.99/月」、Enterprise は「カスタム」に設定
  2. Usage Metering の有効化(Pro / Enterprise)

    • 「Billing」→「Billing Meter」で「api_usage」という meter を作成
    • 「Price」でこの meter を選択して、「使用量 1 単位 = $0.01」のように設定
  3. Webhook の登録

    • 「Developers」→「Webhooks」で /api/stripe/webhooks エンドポイントを登録
    • invoice.payment_succeeded / invoice.payment_failed / customer.subscription.deleted を購読
  4. ウェブフックの送信テスト

    • Stripe CLI を使ってローカルテスト
    stripe listen --forward-to localhost:3000/api/stripe/webhooks
    stripe trigger invoice.payment_succeeded

実運用での学び

個人開発で実際に SaaS を運用して得た知見をいくつか共有します。

支払い失敗への対処

最初は「支払い失敗 → メール通知 → 手で対応」としていましたが、自動化が重要です。失敗したユーザーを自動でダウングレードしておくと、「使えなくなった」というサポート問合せが減ります。

使用量の「バースト」対応

正常なユーザーは「毎日 10 リクエスト」くらいの一定ペースですが、たまに「今月 1,000 リクエスト送ってくる」ユーザーが出ます。これは悪意ではなく、「大量データの処理」や「自動ツール化」が原因です。

ティア設計に「Burst limit」(15分単位での制限)を入れると、サーバー負荷と請求額の両方で安定します。

通知の重要性

ユーザーが「使用量がもうすぐ上限に達する」ことに気づいていないことが多いです。月間利用量の 70% に達した時点でメール+ダッシュボード通知を送ると、アップグレードへの自然な誘導になります。

結び:設計から運用までの全体像

Claude API を使った SaaS 課金は、単に「ボタンを Stripe に接続する」のではなく、API の実コスト → 採算が取れるティア設計 → ユーザーごとの使用量トラッキング → 自動請求と冪等な Webhook → リアルタイム監視 という一連のシステムです。

実装が複雑に見えるかもしれませんが、各パートは独立していて、1つずつ組み立てることができます。

もし今、あなたが「Claude API で SaaS を作りたいけど、どう課金すればいいか分からない」という段階なら、まずは Free / Pro の 2層構造から始めることをお勧めします。リアルなユーザーデータが集まれば、必要な調整が見えてきます。

月間の API コスト計算表を作成し、3パターン(楽観 / 実際 / 悲観)のシナリオで採算を確認してから実装に入ること。これが、赤字になるティア設計を避ける最速の方法です。

シェア

お読みいただきありがとうございます

Claude Lab は広告なしで運営しており、サーバー費用などの運営コストはメンバーシップのご支援で賄っています。実装コード・ベンチマーク・本番設計パターンなど、実務でお役立ていただける記事を毎日更新しています。もし読んでよかったと感じていただけましたら、ぜひご覧ください。

  • コピー&ペーストで使える実装コード付き
  • 毎日新しい上級ガイドを追加
  • ¥580/月 または ¥1,480 の永久アクセス
メンバーシップを見る →

もしこの記事がお役に立ちましたら、チップ(¥150)で応援いただけると大変励みになります。広告なしでの運営を続けるため、皆さまのご支援が大きな力になっています。

関連記事

API & SDK2026-06-24
Claude API の従量課金で、Stripe の請求額と自分の帳簿がズレるとき — 使用量イベントの突合運用メモ
Claude API の従量課金は「使った分だけ請求」が理想ですが、実運用ではStripe側の集計と自前の使用量台帳が静かにズレます。Billing Meters の冪等化・突合ジョブ・モデル変更耐性まで、運用で効いた設計を整理します。
API & SDK2026-06-15
モデルが予告なく使えなくなる日に備える — 引退・撤回・過負荷を一つのステートマシンで扱うルーター設計
あるモデルが、技術的な障害ではなく外部都合で短時間のうちに使えなくなる。引退・撤回・一時的な過負荷という三種の「使えない」を一つの可用性ステートマシンで扱い、自動運用を止めないルーターを TypeScript と Python の動くコードで設計します。
API & SDK2026-06-13
Managed Agents にスケジュールデプロイと vault が加わったので、自前 cron 運用との住み分けを決めた記録
6月12日の更新で Claude Managed Agents にスケジュールデプロイ・vault 環境変数・セッションスレッド Webhook が加わりました。自前の cron と平文クレデンシャル運用から何を移し、何を残すか。冪等性を軸にした判断基準と受け口の実装を残します。
📚RECOMMENDED BOOKS
大規模言語モデル入門
山田育矢
LLM開発
生成AIプロンプトエンジニアリング入門
我妻幸長
プロンプト
Claude CodeによるAI駆動開発入門
平川知秀
AI駆動開発
※ アフィリエイトリンクを含みます
もっと見る →