BrainstormRouter vs Portkey
Architectural comparison: passive control plane vs active intelligence gateway.
What Portkey does well
Portkey is a mature AI gateway with strong fundamentals:
- 1600+ models across 250+ providers
- SOC2 Type II certified
- 20-40ms median latency overhead
- Enterprise features: SSO, RBAC, budget controls
- Observability: request logging, cost tracking, custom metadata
Portkey's strength is breadth. If you need a control plane that sits between your application and many providers, Portkey covers a wide surface.
Where the architectures diverge
Portkey is a passive proxy — it observes, logs, and routes, but it doesn't learn from the traffic it processes. BrainstormRouter is an active intelligence layer — it uses the data flowing through it to make better decisions over time.
%%{init: {'theme': 'dark', 'themeVariables': {'primaryColor': '#d97706', 'lineColor': '#9494a8', 'primaryTextColor': '#e8e8ee'}}}%%
graph LR
subgraph Portkey["Portkey: Passive Proxy"]
direction LR
PC[Client] --> PR[Rules Engine]
PR --> PP[Provider]
PP --> PL[Logger]
PL --> PD[Dashboard]
end
subgraph BR["BrainstormRouter: Active Intelligence"]
direction LR
BC[Client] --> BG[Guardian<br/>Cost prediction]
BG --> BT[Thompson Sampling<br/>Bayesian selection]
BT --> BP[Provider]
BP --> BQ[Quality Scorer]
BQ -->|Feedback loop| BT
BP --> BM[Memory Extraction<br/>Queue]
end
The feedback loop is the fundamental difference. In BrainstormRouter, every response updates the Thompson Sampling weights, which changes future routing decisions. Portkey's routing is configured by rules — it routes the same way on request #1 and request #10,000.
Feature comparison
| Capability | Portkey | BrainstormRouter |
|---|---|---|
| Routing strategy | Rules-based (fallback, loadbalance, conditional) | Thompson Sampling + UCB1 (Bayesian learning) |
| Model selection | Manual configuration | Automatic via multi-armed bandit |
| Quality scoring | Manual evaluations | Automatic validity scoring per response |
| Memory | None | Persistent pgvector memory (Letta-style) |
| Autonomous agents | None (control plane for external agents) | Built-in Pi Runner with tool use |
| Cost prediction | Budget alerts (after the fact) | Pre-request cost estimation (before the call) |
| Circuit breakers | Health checks + retries | Dual-trigger state machine with exponential backoff |
| Response headers | Request ID, latency | Full cost/efficiency/cache data per response |
| Privacy modes | Enterprise data governance | Per-tenant privacy gate (standard/strict) |
| Semantic cache | Prompt caching (simple) | Vector similarity cache with configurable threshold |
| Self-hosted | Enterprise plan only | Open source, deploy anywhere |
Code proof: routing intelligence
Portkey routing
Portkey uses a config-based routing system:
{
"strategy": { "mode": "loadbalance" },
"targets": [
{ "provider": "openai", "weight": 0.7 },
{ "provider": "anthropic", "weight": 0.3 }
]
}
The weights are static. You set them. They don't change based on performance.
BrainstormRouter routing
From src/router/model-bandit.ts:159-180:
private thompsonSelect(arms: BanditArm[]): BanditSelection {
let bestArm = arms[0];
let bestSample = -Infinity;
for (const arm of arms) {
const stddev = arm.sampleCount > 0
? Math.sqrt(Math.max(arm.rewardVar, 0.001) / arm.sampleCount)
: 0.5;
const sampled = arm.rewardMean + gaussianRandom() * stddev;
if (sampled > bestSample) {
bestSample = sampled;
bestArm = arm;
}
}
return { modelKey: bestArm.modelKey, score: bestSample, method: "thompson" };
}
The weights are computed from a posterior distribution that updates with every request. A model that starts failing will see its posterior shift left within ~50 samples. No manual intervention needed.
Code proof: consumption protection
Portkey cost control
Portkey tracks spend and alerts when budgets are exceeded — after the request is made.
BrainstormRouter Guardian
From src/api/middleware/guardian.ts:190-219:
// Pre-request: estimate cost BEFORE making the provider call
const ratio = getOutputInputRatio(tenantId);
const outputTokenEstimate = Math.ceil(inputTokenEstimate * ratio);
const estimatedCostCents = Math.round((inputCost + outputCost) / 1e7);
// Cost seatbelt: reject if over limit (active mode)
if (maxEstimatedCost !== undefined && estimatedCostUsd > maxEstimatedCost) {
if (mode === "active") {
return c.json(
{ error: { message: `Estimated cost exceeds limit`, type: "cost_exceeded" } },
402,
);
}
}
Guardian predicts cost before the provider call using an EWMA output/input ratio. In active mode, it can reject expensive requests before they're made — not after.
Security: logging after delivery is a compliance failure
Portkey logs prompts and responses for observability. This happens after the data has been delivered — to the provider (outbound) and to the client (inbound). If the model outputs PII, that PII reaches your user before Portkey records it.
BrainstormRouter intercepts the streaming response on the hot path:
// From streaming-guardrails.ts:122-168 — processToken()
// Every token is buffered and evaluated BEFORE forwarding to the client
if (result.action === "truncate") {
this.truncated = true;
// All future tokens return "" — stream is severed
return "";
}
| Security capability | Portkey | BrainstormRouter |
|---|---|---|
| Inbound PII scanning | Yes (guardrails) | Yes (built-in + pluggable backends) |
| Outbound stream scanning | No | Yes — token-by-token StreamingGuardrailEvaluator |
| Stream severing | No | Yes — truncated = true kills the stream mid-flight |
| Governance enforcement | No | Yes — deterministic keyword matching, <1ms |
| PII air gap | No | Yes — scrubAndTokenize() / rehydrate() |
| SIEM export | Limited | CEF + ECS JSON via toCef() / toSiemJson() |
| Egress allowlist | No | Yes — per-service domain restrictions |
| Tenant isolation | Org-level access | PostgreSQL RLS with SET LOCAL transaction scoping |
Portkey is a control plane. BrainstormRouter is a security appliance that also routes.
When to choose Portkey
- You need SOC2 certification today
- You need 1600+ model support across 250+ providers
- Your routing rules are simple and static
- You want enterprise SSO and team management
- You don't need memory or autonomous agents
When to choose BrainstormRouter
- You want routing that learns from your traffic
- You need persistent memory across API calls
- You want pre-request cost prediction, not post-request alerts
- You need autonomous background processing (memory extraction, heartbeat)
- You want response-level cost/efficiency headers on every call
- You prefer open source with self-hosting options