Projekte

KeyForge

3 min Lesezeit GitHub
NestJS Next.js Redis PostgreSQL

Jede API, die externe Developer bedient, braucht Key Management. Die meisten Teams starten mit einem gehashten Random String in einer Datenbanktabelle und einem Check bei jedem Request. Dann wachsen die Anforderungen: Rate Limiting pro Key, Usage Tracking, Spend Caps für LLM-Calls, Key Rotation ohne Downtime, Webhooks bei Ablauf, ein Dashboard für Kunden. Jedes Feature ist eine neue Tabelle, ein neues Redis Script, ein neuer Background Job.

Irgendwann hast du ein eigenes Produkt in deinem Produkt gebaut. KeyForge ist dieses Produkt, extrahiert und Open-Source.

Was KeyForge abdeckt

Den kompletten Key Lifecycle. Keys erstellen, verifizieren, rotieren, widerrufen. Rotation unterstützt Grace Periods, damit alte Keys während der Umstellung weiter funktionieren. Kein “deploy new key, pray nothing breaks”.

Drei Rate Limiting Algorithmen. Fixed Window, Sliding Window, Token Bucket. Pro Key konfigurierbar. Enforcement passiert atomar mit Redis Lua Scripts beim Verify-Call. Kein Race Condition Risiko.

Token Budgets und Spend Caps. Monatliche Limits auf Token-Verbrauch und Dollar-Spend. Gebaut für AI/LLM APIs, wo ein Request 100x mehr kosten kann als ein anderer. Ein User, der einen 200k-Token-Prompt schickt, sollte nicht dein Budget für den Monat sprengen.

Usage Metering. Token Counts und Kosten pro Request. Abfragbar als Zeitreihe nach Stunde, Tag oder Monat.

Embeddable React Portal. Ein <KeyPortal /> Component, das du in deine App droppst. Deine Kunden können ihre eigenen Keys verwalten, ohne dass du eine UI bauen musst.

Der Verify Hot Path

Der kritische Pfad ist die Key Verification. Jeder API-Call deiner Kunden geht da durch. Das muss schnell sein.

KeyForge hasht den Key mit SHA-256, schlägt den Hash in Redis nach, prüft Rate Limits und Token Budgets atomar, und antwortet. Alles in einem einzigen Redis Round Trip. Ziel: sub-5ms p95 Latenz.

import { KeyForge } from "@keyforge/sdk";

const kf = new KeyForge({ rootKey: "kf_root_xxx" });

// Express Middleware: eine Zeile
app.use(kf.middleware());

// Oder manuell
const result = await kf.verifyKey("kf_live_xxx", {
  tokens: 1500,
  cost: 0.045,
});

if (!result.valid) {
  // result.code: INVALID | EXPIRED | REVOKED | RATE_LIMITED | BUDGET_EXCEEDED
}

Das SDK liefert Middleware für Express, Fastify, Hono und Next.js. Key extrahieren, verifizieren, Rate Limit Headers setzen. Eine Zeile.

Stack

Turborepo Monorepo mit fünf Packages:

Die API (NestJS + Fastify) handhabt Key Management, Verification, Usage, Webhooks und Billing. PostgreSQL mit Drizzle ORM für den persistenten State. Redis für den Verify Hot Path und atomare Rate Limit Operations via Lua Scripts. BullMQ für Background Jobs: Usage Aggregation, lastUsedAt Syncing, Key Expiration Checks, Webhook Delivery mit Exponential Backoff.

Das Dashboard (Next.js 15) ist die Admin-Oberfläche: Workspaces, Keys, Usage Charts, Webhook Config, Billing.

Deployment: Terraform für AWS (ECS Fargate, RDS, ElastiCache, ALB). Load Tests mit k6 für den Verify Endpoint.

Was ich gelernt hab

Constant-Time Comparison klingt wie ein Textbuch-Thema, bis du realisierst, dass === auf Strings in Node.js early-returnt und damit Timing Attacks möglich macht. crypto.timingSafeEqual existiert aus gutem Grund.

Die andere Erkenntnis: Rate Limiting und Token Budgets sind zwei fundamental verschiedene Probleme. Rate Limiting schützt deine Infrastruktur (Requests pro Sekunde). Token Budgets schützen die Geldbörse deines Kunden (Dollar pro Monat). Beides in einem System zu lösen, mit denselben atomaren Redis Operations, war die eigentliche Herausforderung.