AI APIゲートウェイ設計 — レート制限・認証・ログを一元管理
約5分で読めます
AI APIゲートウェイ設計 — レート制限・認証・ログを一元管理
AIのAPIを複数サービスから呼び出す場合、各サービスに認証やレート制限のロジックを持たせるのは非効率だ。APIゲートウェイで一元管理することで、セキュリティと運用コストを同時に最適化できる。
ゲートウェイの役割
クライアント -> APIゲートウェイ -> AI API(Claude/OpenAI等)
+-- 認証・認可
+-- レート制限
+-- リクエストログ
+-- コスト追跡
+-- キャッシュ
Cloudflare Workers実装例
// wrangler.toml の KV namespace: RATE_LIMIT, CACHE, API_KEYS
export default {
async fetch(request, env) {
// 1. 認証チェック
const apiKey = request.headers.get("X-API-Key");
const keyData = await env.API_KEYS.get(apiKey, { type: "json" });
if (!keyData) {
return new Response("Unauthorized", { status: 401 });
}
// 2. レート制限チェック
const rateLimitKey = `rate:${apiKey}:${currentMinute()}`;
const current = parseInt(await env.RATE_LIMIT.get(rateLimitKey) || "0");
if (current >= keyData.rateLimit) {
return new Response("Rate limit exceeded", {
status: 429,
headers: { "Retry-After": "60" }
});
}
await env.RATE_LIMIT.put(rateLimitKey, String(current + 1), {
expirationTtl: 120
});
// 3. キャッシュチェック(同一プロンプトの重複排除)
const body = await request.json();
const cacheKey = `cache:${hashRequest(body)}`;
const cached = await env.CACHE.get(cacheKey);
if (cached) {
return new Response(cached, {
headers: { "X-Cache": "HIT", "Content-Type": "application/json" }
});
}
// 4. AI APIへプロキシ
const aiResponse = await fetch("https://api.anthropic.com/v1/messages", {
method: "POST",
headers: {
"x-api-key": env.ANTHROPIC_API_KEY,
"anthropic-version": "2023-06-01",
"Content-Type": "application/json"
},
body: JSON.stringify(body)
});
const responseData = await aiResponse.text();
// 5. キャッシュ保存(TTL: 1時間)
await env.CACHE.put(cacheKey, responseData, { expirationTtl: 3600 });
// 6. ログ記録
await logRequest(env, {
apiKey: apiKey,
model: body.model,
inputTokens: JSON.parse(responseData).usage?.input_tokens,
outputTokens: JSON.parse(responseData).usage?.output_tokens,
timestamp: Date.now()
});
return new Response(responseData, {
headers: { "X-Cache": "MISS", "Content-Type": "application/json" }
});
}
};
function currentMinute() {
return Math.floor(Date.now() / 60000);
}
function hashRequest(body) {
return btoa(JSON.stringify(body)).slice(0, 64);
}
AWS API Gateway + Lambda構成
# serverless.yml
service: ai-api-gateway
provider:
name: aws
runtime: nodejs20.x
region: ap-northeast-1
functions:
proxy:
handler: handler.proxy
events:
- http:
path: /v1/messages
method: post
cors: true
environment:
ANTHROPIC_API_KEY: ${ssm:/ai-gateway/anthropic-key}
usage-report:
handler: handler.usageReport
events:
- schedule: rate(1 day)
resources:
Resources:
UsagePlan:
Type: AWS::ApiGateway::UsagePlan
Properties:
Throttle:
RateLimit: 100
BurstLimit: 200
Quota:
Limit: 10000
Period: DAY
レート制限の設計指針
| プラン | リクエスト/分 | 日次上限 | 月次トークン上限 |
|---|---|---|---|
| Free | 10 | 100 | 100K |
| Basic | 60 | 1,000 | 1M |
| Pro | 300 | 10,000 | 10M |
| Enterprise | カスタム | カスタム | カスタム |
レート制限はリクエスト数だけでなくトークン数でも制御する。大きなプロンプトを少量送るパターンと、小さなプロンプトを大量に送るパターンの両方を制御できる。
コスト追跡ダッシュボード
リクエストログからAPIキーごとのコストを集計し、予算超過をアラートする。
def calculate_daily_cost(logs: list[dict]) -> dict:
"""APIキーごとの日次コストを集計"""
costs = {}
pricing = {
"claude-haiku-4-5-20250901": {"input": 0.25, "output": 1.25},
"claude-sonnet-4-5-20250514": {"input": 3.0, "output": 15.0},
"claude-opus-4-6-20250901": {"input": 15.0, "output": 75.0},
}
for log in logs:
model = log["model"]
price = pricing.get(model, {"input": 3.0, "output": 15.0})
cost = (
log["inputTokens"] / 1_000_000 * price["input"]
+ log["outputTokens"] / 1_000_000 * price["output"]
)
costs[log["apiKey"]] = costs.get(log["apiKey"], 0) + cost
return costs
セキュリティのポイント
- APIキーのローテーション: 90日ごとに自動ローテーション
- IPホワイトリスト: Enterprise顧客には送信元IP制限を提供
- プロンプトインジェクション防御: 入力サニタイズをゲートウェイ層で実施
- PII検出: 個人情報を含むリクエストをブロックまたはマスキング
まとめ
AI APIゲートウェイは「認証 + レート制限 + コスト追跡」を一元化する。Cloudflare Workersなら低レイテンシでグローバル展開でき、AWS API Gatewayなら既存AWS環境との統合が容易だ。
関連記事
A
Agentive 編集部
AIエージェントを実際に使い倒す個人開発者。サイト制作の自動化を実践しながら、その知見を発信しています。