Architecture
Binom.Router is a high-throughput, modular gateway for AI providers. It is built as a distributed system of focused microservices that share a unified, OpenAI-compatible API surface while keeping each bounded context small, replaceable, and horizontally scalable.
Overview
At its core, Binom.Router routes chat-completion requests from end users to the best available AI provider (OpenAI, Anthropic, Google Gemini, OpenRouter, NVIDIA, and others). The platform is decomposed into eight bounded contexts, each with a single responsibility and a strict list of things it is not allowed to do:
| Service | Responsibility | Local state |
|---|---|---|
| 🆔 Identity | Authentication, user lifecycle, API keys, token issuance | PostgreSQL + OpenIddict |
| 💳 Billing | Subscriptions, wallets, payments (Stripe + crypto), usage accounting | PostgreSQL |
| 🌐 Gateway | YARP routing, rate limiting, API key validation, streaming | None (stateless) |
| ⚙️ Api | Domain logic, model catalog, routing configuration, DB interactions | PostgreSQL (ApiDbContext) |
| 🤖 Worker | AI inference execution, connectors, hardware monitoring, heartbeat | LiteDB (node-local) |
| 💰 CryptoProcessor | Blockchain monitoring (EVM, Solana, Tron, UTXO), deposit detection | PostgreSQL |
| ✉️ Mailer | Transactional and notification email delivery | PostgreSQL |
| 🛠️ Provisioner | Infrastructure provisioning and lifecycle automation | PostgreSQL |
The front end is a Blazor Web App (SSR + WebAssembly) that communicates with the back end through a dedicated Web BFF (Backend-for-Frontend). The BFF is the only entry point for the UI; browser code never talks to microservices directly.
Technology Stack
Platform & Runtime
| Technology | Version | Role |
|---|---|---|
| .NET | 10.0 | Primary runtime across all services |
| ASP.NET Core | 10.0.9 | Web APIs and Blazor hosting |
| Blazor WebAssembly | 10.0.8 | Interactive client UI |
| Blazor Web App | 10.0.9 | Server-side rendering + WASM hosting |
Orchestration & Infrastructure
| Technology | Version | Role |
|---|---|---|
| .NET Aspire | 13.4.5 | AppHost orchestration, ServiceDefaults |
| PostgreSQL | — | Primary transactional store |
| RabbitMQ | — | Message broker for Wolverine |
| Redis | — | Distributed cache, rate-limiting counters, SignalR backplane |
| Garnet | — | High-performance distributed cache |
| Docker | — | Local containerized dependencies |
Messaging & Integration
| Package | Version | Role |
|---|---|---|
| WolverineFx | 6.13.0 | CQRS command and event bus |
| WolverineFx.RabbitMQ | 6.13.0 | RabbitMQ transport |
| WolverineFx.Postgresql | 6.13.0 | PostgreSQL outbox persistence |
| WolverineFx.EntityFrameworkCore | 6.13.0 | EF Core integration for handlers |
| WolverineFx.MessagePack | 6.13.0 | Binary message serialization |
| MessagePack | 3.1.7 | Internal binary protocol |
| Microsoft.AspNetCore.SignalR.Protocols.MessagePack | 10.0.9 | Binary SignalR payloads |
Data & Caching
| Package | Version | Role |
|---|---|---|
| EF Core | 10.0.9 | Object-relational mapping |
| Npgsql | 10.0.2 | PostgreSQL driver |
| Npgsql.EntityFrameworkCore.PostgreSQL | 10.0.2 | EF Core PostgreSQL provider |
| StackExchange.Redis | 3.0.0 | Redis client |
| LiteDB | 5.0.21 | Worker node-local metadata |
| Microsoft.Extensions.Caching.StackExchangeRedis | 10.0.9 | Distributed caching |
Authentication & Authorization
| Package | Version | Role |
|---|---|---|
| OpenIddict.AspNetCore | 7.5.0 | OAuth 2.0 / OpenID Connect server and validation |
| OpenIddict.Validation.AspNetCore | 7.5.0 | ASP.NET Core token validation |
| OpenIddict.Validation.SystemNetHttp | 7.5.0 | Outgoing token validation |
| OpenIddict.Client.AspNetCore | 7.5.0 | Web BFF OAuth client (cookie flow) |
| Microsoft.AspNetCore.Authentication.Google | 10.0.9 | Google OAuth |
| AspNet.Security.OAuth.GitHub | 10.0.0 | GitHub OAuth |
UI & Presentation
| Package | Version | Role |
|---|---|---|
| Masa.Blazor | 1.11.9 | Component library for Blazor |
| Markdig | 1.3.2 | Markdown rendering (this documentation) |
| QRCoder | 1.8.0 | QR-code generation |
AI Abstractions & Providers
| Package | Version | Role |
|---|---|---|
| Microsoft.Extensions.AI | 10.7.0 | Unified AI abstraction layer |
| Microsoft.Extensions.AI.OpenAI | 10.7.0 | OpenAI-compatible provider support |
| OpenAI SDK | 2.11.0 | Native OpenAI client |
| Microsoft.DeepDev.TokenizerLib | 1.3.3 | Token counting |
| Microsoft.Playwright | 1.60.0 | Browser automation for connector auth |
Proxy, Resilience & Observability
| Package | Version | Role |
|---|---|---|
| YARP.ReverseProxy | 2.3.0 | Reverse proxy in Gateway and Web BFF |
| Microsoft.Extensions.ServiceDiscovery.Yarp | 10.7.0 | Aspire service discovery for YARP |
| Polly | 8.7.0 | Resilience policies |
| Microsoft.Extensions.Http.Polly | 10.0.9 | HttpClient resilience |
| Microsoft.Extensions.Http.Resilience | 10.7.0 | Resilience abstractions |
| OpenTelemetry.Exporter.OpenTelemetryProtocol | 1.16.0 | OTel export |
| OpenTelemetry.Extensions.Hosting | 1.16.0 | OTel host integration |
| OpenTelemetry.Instrumentation.AspNetCore | 1.15.2 | ASP.NET Core telemetry |
| OpenTelemetry.Instrumentation.Http | 1.15.1 | HttpClient telemetry |
| OpenTelemetry.Instrumentation.Runtime | 1.15.1 | Runtime telemetry |
Crypto & Payments
| Package | Version | Role |
|---|---|---|
| Stripe.net | 52.0.0 | Card payments |
| NBitcoin | 10.0.7 | Bitcoin / UTXO |
| Nethereum.Web3 | 6.1.0 | EVM chains |
| Solnet.Rpc / Solnet.Wallet / Solnet.Programs | 6.1.0 | Solana |
| TronNet | 0.2.0 | TRON |
| Package | Version | Role |
|---|---|---|
| MailKit | 4.17.0 | Email client |
| MimeKit | 4.17.0 | MIME message building |
Testing
| Package | Version | Role |
|---|---|---|
| xUnit | 2.9.3 | Unit and integration test framework |
| xunit.runner.visualstudio | 3.1.5 | Test runner |
| FluentAssertions | 8.10.0 | Expressive assertions |
| Moq | 4.20.72 | Mocking library |
| NSubstitute | 5.3.0 | Alternative mocking library |
| Microsoft.AspNetCore.Mvc.Testing | 10.0.9 | In-memory API test host |
| Testcontainers | 4.12.0 | Containerized PostgreSQL / RabbitMQ / Redis for tests |
| WireMock.Net | 2.11.0 | HTTP stubbing for integration tests |
| Microsoft.Playwright | 1.60.0 | Browser-based UI tests |
| Aspire.Hosting.Testing | 13.4.5 | Aspire app host integration tests |
Architectural Patterns
- Clean Architecture —
Domain → Application → Infrastructure → Presentation/Api. Domain logic has no external dependency references. - CQRS via WolverineFx — Commands and events are explicit,
sealed classmessages. Read/write sides are shaped by use cases, not generic CRUD. - No Repository / No Unit of Work —
DbContextis used directly inside command handlers. No extra abstractions are introduced over EF Core. - No Auto-Mapper — Mapping is explicit through static
DtoMapperandDomainMapperclasses. - Reflection-free (AOT-safe) —
System.Reflectionis prohibited. Serialization and token handling use source-generated or manual code paths. - Backend-for-Frontend (BFF) — The Blazor Web App server proxies UI traffic to Gateway via YARP and keeps tokens out of browser code with cookie-based sessions.
- PostgreSQL Outbox — Wolverine persists outbound messages in PostgreSQL before publishing them to RabbitMQ for at-least-once delivery guarantees.
- 4-Tier Limit System — Spending and throughput limits are enforced at Worker → Connector → Account → Model levels, evaluated atomically through Redis Lua scripts.
Request Flow
A typical chat-completion request travels from the user to the upstream AI provider and back through a clear chain of responsibilities:
flowchart LR
Browser["🖥️ Blazor WASM"] -->|"HTTPS + Cookie"| BFF["🌐 Web BFF<br/>YARP"]
BFF -->|"Bearer + Routing"| Gateway["🛡️ Gateway<br/>API key, rate limit, limits"]
Gateway -->|"Route /v1/chat/completions"| Api["⚙️ Api<br/>Domain logic, model selection"]
Api -->|"Dispatch job"| Worker["🤖 Worker<br/>Connector execution"]
Worker -->|"Native or OpenAI-compatible"| Provider["☁️ AI Provider"]
Provider -->|"SSE stream"| Worker
Worker -->|"Binary internal stream"| Api
Api -->|"SSE / text/event-stream"| Gateway
Gateway -->|"Proxied stream"| BFF
BFF -->|"SSE"| Browser
Key points:
- The browser sees only the Web BFF and uses HTTP-only cookies.
- Gateway enforces authentication, rate limiting, and the hierarchical limit chain.
- Api owns domain routing decisions and dispatches work to Workers.
- Worker executes the actual model call and applies any browser/API connector logic.
- Streaming flows back in the opposite direction using SSE externally and MessagePack streams internally.
Service Boundaries
| Service | Can do | Cannot do |
|---|---|---|
| Identity | Authenticate users and services, issue tokens, manage API keys and OAuth clients | Billing logic, worker management, business entities |
| Billing | Subscriptions, wallets, Stripe/crypto payments, usage aggregation, real-time SignalR balance updates | Direct authentication, infrastructure provisioning |
| Gateway | Route requests (YARP), validate API keys, Redis rate limiting, proxy streaming | Persistent state, business logic, AI execution, DbContext |
| Api | Domain rules, model catalog, routing graph, command/event handlers, ApiDbContext |
Proxy traffic to external services (except LLM providers), validate users directly |
| Worker | Run inference, manage connectors, heartbeat, hardware metrics, LiteDB state | Direct user interaction, billing decisions |
| CryptoProcessor | Monitor blockchains, detect deposits, generate addresses | Authentication, business logic |
| Mailer | Send transactional and marketing email | Anything outside mail delivery |
| Provisioner | Provision infrastructure resources on demand | Direct user interaction |
Why Binom.Router?
- Unified API — One OpenAI-compatible endpoint for many providers; migrate models without changing client code.
- Resilient routing — Automatic failover and load balancing across workers, accounts, and connectors.
- Real-time billing — Token usage is tracked and billed as it happens; balances update through SignalR.
- Binary internal protocol — MessagePack reduces wire overhead and boosts throughput between services.
- AOT-ready — Reflection-free design keeps the door open for native compilation and trimmed deployments.
- Clear ownership — Every service has narrow responsibilities and explicit forbidden areas, which keeps the architecture honest as it grows.