Zurück zur Dokumentation
Guide 00

Quotas und Kosten — Nutzungs- und Ausgaben-Obergrenzen

Die Quota-Engine deckt drei Gattungen ab: die Token-Quota und die Storage-Quota (Phase 207) samt der Kosten-Quota (Phase 216, hold-and-settle über die echte-Geld-Mathematik). Die Quotas sind das Betreiberwerkzeug für Nutzungsobergrenzen in Mehrbenutzer-I…

4 Min. Lesezeit

Die Quota-Engine deckt drei Gattungen ab: die Token-Quota und die Storage-Quota (Phase 207) samt der Kosten-Quota (Phase 216, hold-and-settle über die echte-Geld-Mathematik). Die Quotas sind das Betreiberwerkzeug für Nutzungsobergrenzen in Mehrbenutzer-Installs; sie binden jeden Benutzer mit konfigurierter Quota — Administratoren eingeschlossen — und eine nicht gesetzte Quota heißt unbegrenzt (fail-open: null Verhaltensänderung für bestehende Installs).

Community-Funktion (Betreiberwerkzeug). Quellen: docs/QUOTAS.md (Phase 207 + 216), docs/MODEL_COSTS.md, docs/API.md (der Abschnitt Costs, quotas, and per-user model policy). Provenienz-Zeilen: FACT-CENSUS.md F-QUOTA-1.

Die Kern-Invarianten

  • Kein zweiter Zähler. Die Wahrheit des Verbrauchs (Token/Kosten) bleibt beim bestehenden Ledger WorkspaceTokenUsage (packages/server/src/services/quotaService.ts). QuotaBalance / QuotaHold / QuotaReset sind abgeleiteter und geankerter Zustand, keine Zählungstabelle.
  • Reset = Ledger-Anker. Ein Reset schreibt erneut QuotaReset(kind, at), das das rollierende Fenster begrenzt — die Geschichte von Nutzung/Kosten wird nie gelöscht oder genullt.
  • Gate auf Service-Ebene, pre-turn — KEIN Auth-Middleware (der Check braucht Domänen-Daten, nicht die Form der Anfrage). Die Gates starten vor dem ersten LLM-Aufruf im Orchestrator und vor der Ingest auf den Upload-Pfaden.
  • Fail-open bei nicht gesetzten Quotas. Die Auflösungskette endet auf „unbegrenzt", wenn nichts konfiguriert ist (D-08).
  • Die Geldmathematik ist Decimal→cents. SÄMTLICHE Kostenarithmetik läuft über Prisma.Decimal und landet als ganze cents — nie float (costQuotaService.ts, die COST-01-Doktrin).

Die Auflösungskette (D-08)

EbeneQuelleHinweise
1Pro-Benutzer-OverrideUser.tokenQuotaLimit / User.storageQuotaGb / die Kosten-Zeilen pro Benutzer — via PUT /api/quota/:userId (admin)
2Installations-PresetDie SystemConfig-Schlüssel (unten) — DB > ENV > Default
3UnbegrenztDie Sentinel "0" / "" / unset = nicht konfiguriert → fail-open

Die Konfigurationsschlüssel (SystemConfig, admin-editierbar via Settings)

SchlüsselStandardBedeutung
QUOTA_TOKEN_DEFAULTunset-SentinelDie Token-Obergrenze der Installs für jeden Benutzer ohne Override
QUOTA_STORAGE_GB_DEFAULTunset-SentinelDie Storage-Obergrenze der Installs (GB)
QUOTA_COST_EUR_DEFAULTunset-Sentinel ("0"/"" = unbegrenzt)Die KOSTEN-Obergrenze der Installs — DEZIMALZEICHENKETTE EUR
QUOTA_COST_FALLBACK_INPUT_CENTS_PER_1Mintegrierter Floor ungleich nullDer SC-4-Fallback-Tarif für Modelle OHNE Preis — input, ganze cents pro 1M Token
QUOTA_COST_FALLBACK_OUTPUT_CENTS_PER_1Mintegrierter Floor ungleich nullDer SC-4-Fallback-Tarif für Modelle OHNE Preis — output

Die SC-4-Doktrin: ein Modell ohne Preis umgeht die Kosten-Quota NIEMALS — die Fallback-Tarife greifen mit warn-once (warnFallbackOnce): ein preisloses Modell kann nie als gratis gelten.

Token-Quotas (quotaService.ts)

  • resolveTokenQuota(userId) → { limit, source } — limit: null = unbegrenzt; source sagt, welche Ebene der D-08 entschieden hat.
  • Das rollierende Fenster startet am letzten QuotaReset-Anker für (userId, kind: "token") (oder an der Epoche, falls nie zurückgesetzt); die In-Fenster-Nutzung summiert sich vom Ledger WorkspaceTokenUsage.
  • Das Überschreiten der Quota wirft QuotaError (status + payload) — das Feld quota des Payloads ist der Vertrag, den frontend, widget und die Connector-Handler lesen. Es gibt keine Middleware zum Umgehen: das Gate läuft INNERHALB des Service-Pfads.

Kosten-Quotas (costQuotaService.ts, Phase 216) — hold-and-settle

Die zweiphasige Buchung:

  1. Reserve (vor dem LLM-Aufruf) — reserveCostQuota(principal, estimateCents) fährt EINE interaktive Transaktion: ein bedingtes updateMany, dessen Prädikat (spentCents + estimate <= limitCents) Postgres mit row-lock auswertet, sodass N konkurrierende Gates sich SERIALIZIEREN statt alle über einen alten Check zu laufen (SC-2) + das QuotaHold-Insert in derselben Transaktion.
  2. Settle (beim Nutzungsabschnitt) — settleCostHold schließt den hold und erstattet estimate − actual zurück. Der In-flight-Overshoot (actual > estimate) ist das akzeptierte Fenster — kein Kill bei laufendem Stream.
  3. Im Ruhezustand gilt die Invariante: settledSpent + Σ(offene lead) ≤ limit.
  4. Die Preisquelle je Zeile: der FROZEN-Snapshot von Phase 203, wo vorhanden; sonst die SC-4-Fallback-Tarife (warn-once); Zeilen in einer Nebenwährung werden trotzdem bepreist (nie still gratis, nie ausgeschlossen).
  5. Reset — resetCostQuota schreibt den Quota(kind "cost")-Anker und baut das Guthaben aus Ledger-Summe + offenen holds neu auf (D-02).

Storage-Quotas

checkStorageQuota / resolveStorageQuota erzwingen den Pro-Benutzer-Override storageQuotaGb, das Preset QUOTA_STORAGE_GB_DEFAULT oder das Unbegrenzte. Die Gates starten auf den Upload-Pfaden vor dem Dispatch zum Collector.

Der Principal für Widgets

Die anonymen Widget-Besucher sind keine Benutzer — resolveWidgetQuotaPrincipal bindet den Widget-Traffic an den Principal der Organisation des Widgets: der Widget-Verbrauch wächst auf der Quota-Kette der Organisation, nicht auf per-Besucher-Identitäten.

Wo die Gates starten (die Verbrauchsstellen)

OberflächeGateDatei
Chat (JWT, widget proxy, connector — ein orchestrator)Token- + Kosten-Gate pre-turn / pre-LLMpackages/server/src/agent/orchestrator.ts
Dokument-Uploaddas Storage-Gate pre-ingestpackages/server/src/routes/uploads.ts, routes/documents.ts
Das Reset-Sweepstündlicher Token-Quota-Reset (pg-boss cron: initQuotaResetScheduler)services/quotaResetJob.ts
Die self-service AbrufeGET /api/quota/me, rollups, manueller Resetroutes/quota.ts

Der Betreiber-Workflow

  1. Der Installations-Default — Settings-UI → die QUOTA_*-Schlüssel (oder PUT /api/system/settings).
  2. Der Pro-Benutzer-Override — PUT /api/quota/:userId (admin) oder die Quota-UI.
  3. Die Pro-Benutzer-Preise — die COSTS-Familie (Phase 209: /api/users/:userId/pricing, die own-provider-Schlüssel unter /api/me/provider-keys) speist dieselbe Engine.
  4. Der manuelle Reset jederzeit: POST /api/quota/:userId/reset; der stündliche Sweep trägt den Ruhezustand.

Die Modell-Preise (MODEL_COSTS)

Setup: Settings → Providers → den Provider wählen → die Model-action pricing → der Kostenwert pro 1M-Token input/output (z. B. 1.50 und 6.00) + die Währung → Save. Die Formel: cost = tokens × rate, serverseitig bei jedem Nutzungs-Schreibzugriff berechnet, mit einem zur Laufzeit eingefrorenen Snapshot (spätere Tarifänderungen schreiben die Geschichte nie um). Währungen: USD, EUR, GBP, JPY, CNY, INR — Summen je Währung, keine Konversion in v1. N/A = Preis nicht konfiguriert (die Cloud-Modelle unset; die UI zeigt „N/A" — der Admin muss konfigurieren); $0.00 = ausdrücklich gratis (die lokalen/Ollama-Modelle wurden im backfill zur Migration auf 0 gesetzt; Override möglich). Die v1-Grenzen: keine Währungskonversion; nur die Kosten der Hauptiteration (die Sub-Pipelines tool/MCP/synthesis ausgeschlossen); die Kosten stehen beim done-Ereignis zur Verfügung (nicht zur Stream-Mitte).

Die Endpunkt-Referenz

Die volle Tabelle lebt in API reference → Costs, quotas, and per-user model policy.

Siehe auch

  • Scaling — das Quota-Verhalten bei Multi-Instanz-Deployment

Diese Anleitung behandelt die Betriebsoberfläche für die Quotas und Kosten; die technische Tiefe steckt im Zwillingsbeitrag:

Provenance

AbschnittQuelle
Invarianten / Auflösungskette / Schlüsseldocs/QUOTAS.md (core invariants, D-08, die Schlüssel — Phase 207/203) — F-QUOTA-1
Kosten-Quotas / hold-and-settledocs/QUOTAS.md (§ Cost quotas — Phase 216) + costQuotaService.ts
Modell-Preisedocs/MODEL_COSTS.md (Phase 203/209/216)
Die Gate-Stättendocs/QUOTAS.md (§ Where the gates fire)

---

Betreiber-Referenz — Simmetric Chat v0.28.1 (Dokumente aktualisiert am 2026-10-02, Census-SHA `aca5b8ff`).