Rate Limits — 500 円 / user モデルと API units
設計の基本方針
TAS-CHA は 個人 500 円 / 組織 500 円 × user を共通の単価としており、 API 連携でも別 Tier を切らない。
代わりに以下で公平利用を担保する:
- API units (月次): 全リソースを共通の "重み付け" 単位で計測
- 短期 burst (60 秒固定 window): 同時並行の濫用を抑制
- どちらも paid seats に比例して増える
quota / burst の既定値はプランごとに定義され、 paid seats に応じて評価される。
推奨既定値
| 制御対象 | 値 | 備考 |
|---|---|---|
| 月次 API units | 20,000 units × paid seats | 個人 1 seat でも 20,000 |
| 月次 minimum | 20,000 units | 組織 1 名でも同じ |
| billing entity burst | max(300, 60 × seats) req/min | 上限 cap 3,000 req/min |
| API key burst | 120 req/min | key 単位の隔離 |
| Actor burst | 120 req/min | user/app/agent ごと |
| Write burst | 30 req/min | 高コスト操作向け |
| Webhook delivery | 600 deliveries/min | 超過は queue で遅延、 破棄しない |
| OpenClaw agent run | 10 runs/min, 3 concurrent/entity | queue 化前提 |
| MCP tool call | 120 req/min | - |
組織は apiUnitsPerSeatPerMonth × paid seats を最小保証 (apiUnitsMonthlyMinimum) と比較し、 大きい方を採用する。
API unit weight
| 操作 | units |
|---|---|
REST read (例: GET /v1/rooms) | 1 |
| REST write | 3 |
| File metadata / list | 1 |
| File download / upload initiation | 5 |
| Webhook delivery attempt | 1 |
| MCP read tool | 2 |
| MCP write tool | 5 |
| Connector action run | 10 |
| OpenClaw agent run | 20 |
高コスト操作だけ重みを大きくして原価と濫用リスクを吸収する。
評価順
すべての /v1/... リクエストは以下の順で評価される:
- 認証 (API key or OAuth bearer)
- actor 解決 (user / app / agent)
- scope 検査
- ドメイン権限 (org / room / RBAC / room type)
- 短期 burst limit (entity / api_key / actor / write group)
- 月次 API units reservation
- idempotency 検査 (write のみ)
- ドメイン処理
- 成功時 confirm / 失敗時 release
monthly quota は 予約パターン: 処理前に units を reserve し、 処理失敗時には release する。 確定後 confirmed_units に積まれる。
レスポンスヘッダー
成功時
X-Request-Id: req_01JY...
RateLimit-Limit: 300
RateLimit-Remaining: 287
RateLimit-Reset: 42
RateLimit-Policy: 300;w=60
Tascha-Api-Units-Limit: 60000
Tascha-Api-Units-Remaining: 58437
Tascha-Api-Units-Used: 1563
Tascha-Api-Units-Cost: 3
Tascha-Api-Units-Reset: 2026-07-01T00:00:00+09:00
Tascha-RateLimit-Scope: organization
Tascha-RateLimit-Subject: org_XXX
無制限プランの場合: burst / 月次 units が無制限の軸については、 対応する
RateLimit-*/Tascha-Api-Units-Limit/Tascha-Api-Units-Remainingヘッダー 自体が省略される (0は返さない)。 ヘッダーが無い場合、 クライアントは当該軸の 制限なしとして扱うこと。
Burst 超過 (429)
HTTP/1.1 429 Too Many Requests
Retry-After: 42
RateLimit-Remaining: 0
{
"error": {
"code": "rate_limit_exceeded",
"message": "Too many requests. Retry after 42 seconds.",
"requestId": "req_01JY...",
"details": {
"kind": "burst",
"scope": "organization",
"retryAfterSeconds": 42
}
}
}
月次 API units 枯渇 (429)
{
"error": {
"code": "api_units_exceeded",
"message": "Monthly API units quota has been exhausted.",
"requestId": "req_01JY...",
"details": {
"kind": "monthly_units",
"limit": 60000,
"remaining": 0,
"resetAt": "2026-07-01T00:00:00+09:00"
}
}
}
クライアントが取るべき挙動
- 全レスポンスから
RateLimit-Remainingを読み、 0 に近づいたら 自発的に減速 - 429 を受けたら
Retry-Afterの秒数まで待ってから再試行 api_units_exceededは 1 ヶ月先まで回復しない。 即時 retry せず、 ユーザーに通知 or 機能停止- 監視 dashboard に
Tascha-Api-Units-Remainingを出すと早期警告できる (80% / 95%)
fail-closed
rate limit backend (Redis / DB) が落ちた場合、 TAS-CHA は fail-closed (= 503 で全リクエストを止める) を採用する。 これは設計判断。 「障害時は無制限」よりも「障害時は止まる」を優先する。
既存 /api/... との関係
既存 frontend 用 /api/... には RateLimit-* ヘッダーは 付かない (後方互換のため)。 Public API・Remote MCP・Connector admin API のみが対象。
Webhook 配信 (TAS-CHA → 外部) には受信側向けの RateLimit-* を付けない。 代わりに /v1/rooms/:roomId/webhooks/:webhookId/deliveries で配信状況を確認できる (Webhook v2)。