Router Transport Plugins
StellaOps Router uses a plugin-based transport architecture that enables runtime loading of transport implementations. This allows operators to deploy only the transports they need and swap implementations without recompiling the Gateway.
Available Transports
| Transport | Plugin Assembly | Use Case | Status |
|---|---|---|---|
| TCP | StellaOps.Router.Transport.Tcp.dll | Internal services, same datacenter | Stable |
| TLS | StellaOps.Router.Transport.Tls.dll | Cross-datacenter, mTLS | Stable |
| UDP | StellaOps.Router.Transport.Udp.dll | Fire-and-forget, broadcast | Stable |
| RabbitMQ | StellaOps.Router.Transport.RabbitMq.dll | Async processing, fan-out | Stable |
| InMemory | StellaOps.Router.Transport.InMemory.dll | Development, testing | Stable |
| Valkey | StellaOps.Messaging.Transport.Valkey.dll | Distributed, pub/sub | Stable |
| PostgreSQL | StellaOps.Messaging.Transport.Postgres.dll | Transactional, LISTEN/NOTIFY | Stable |
Plugin Architecture
Loading Model
Transport plugins are loaded at Gateway startup via RouterTransportPluginLoader:
The gateway host must not depend on concrete optional transport server classes.
Transport implementations expose gateway-owned contracts from
`StellaOps.Router.Common`: connection-oriented transports register
`IGatewayConnectionTransportServer`, while queue-backed messaging registers
`IGatewayMessagingTransportServer`. The host dispatch path consumes those
contracts so TCP, TLS, RabbitMQ, UDP, InMemory, and non-default messaging
backends can move to signed mounted bundles without changing gateway service
code. The gateway runtime project no longer references concrete Router
transport or Messaging backend implementations; the default Messaging + Valkey
path must be supplied by mounted bundles.
┌─────────────────────────────────────────────────────────────────┐
│ Gateway Startup │
│ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ RouterTransportPluginLoader │ │
│ │ │ │
│ │ 1. Scan plugins/router/transports/ │ │
│ │ 2. Load assemblies in isolation (AssemblyLoadContext) │ │
│ │ 3. Discover IRouterTransportPlugin implementations │ │
│ │ 4. Register configured transport with DI │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │ │
│ ▼ │
│ ┌────────────────────────────────────────────────────────────┐ │
│ │ Transport Plugin (e.g., TLS) │ │
│ │ │ │
│ │ - TransportName: "tls" │ │
│ │ - DisplayName: "TLS Transport" │ │
│ │ - IsAvailable(): Check dependencies │ │
│ │ - Register(): Wire up ITransportServer/ITransportClient │ │
│ └────────────────────────────────────────────────────────────┘ │
│ │
└──────────────────────────────────────────────────────────────────┘
Directory Structure
Mounted bundle roots use profile/plugin-id directories and are mounted read-only into the gateway container:
devops/plugins/
|-- router/
| `-- <profile>/
| `-- <plugin-id>/
| |-- StellaOps.Router.Transport.<Name>.dll
| |-- StellaOps.Router.Transport.<Name>.dll.sig
| |-- transports.signed.json
| `-- checksums.sha256
`-- messaging/
`-- <profile>/
`-- <plugin-id>/
|-- StellaOps.Messaging.Transport.<Name>.dll
|-- StellaOps.Messaging.Transport.<Name>.dll.sig
|-- manifest.json
`-- checksums.sha256
Compose mounts these roots under /app/plugins/router/... and /app/plugins/messaging/...; trust roots mount under /app/trust-roots/plugins/{router,messaging}.
The runtime packager produces the default Messaging/Valkey bundles for the base profile, Router TLS plus Messaging PostgreSQL for the recommended profile, and Router InMemory plus Messaging InMemory for the harness profile. TCP, RabbitMQ, UDP, and other non-default transports remain future profile work until their compose dependencies and admission tests are added.
Router transport bundles use the signed Router transport manifest admitted by RouterTransportPluginLoader. Messaging backend bundles use the same profile/plugin-id shape and are admitted by MessagingPluginLoader with the configured trust root, profile, and signature-enforcement setting. Gateway startup wires those values from Gateway:MessagingBackendPlugins and mirrors them into Gateway:Transports:Messaging; non-development startup forces signature verification on.
The older flat layout below is retained only for legacy image-staged mode and local migration context; mounted runtime mode uses the profile/plugin-id layout above.
plugins/
└── router/
└── transports/
├── StellaOps.Router.Transport.Tcp.dll
├── StellaOps.Router.Transport.Tls.dll
├── StellaOps.Router.Transport.Udp.dll
├── StellaOps.Router.Transport.RabbitMq.dll
└── StellaOps.Router.Transport.InMemory.dll
Configuration
Transport selection and options are configured in router.yaml or environment variables:
Router:
Transport:
Type: tls # Which transport plugin to use
Tls: # Transport-specific options
Port: 5101
CertificatePath: /certs/server.pfx
RequireClientCertificate: true
Tcp:
Port: 5100
MaxConnections: 1000
Environment override:
ROUTER__TRANSPORT__TYPE=tcp
ROUTER__TRANSPORT__TCP__PORT=5100
Using Plugins in Gateway
Programmatic Loading
using StellaOps.Router.Common.Plugins;
var builder = WebApplication.CreateBuilder(args);
// Load transport plugins from signed profile/plugin-id bundle directories.
var pluginLoader = new RouterTransportPluginLoader(
builder.Services.BuildServiceProvider().GetService<ILogger<RouterTransportPluginLoader>>());
var profileRoot = "/app/plugins/router/base";
foreach (var bundlePath in TransportPluginDirectoryProbe.GetSignedManifestLoadCandidateDirectories(
profileRoot,
"StellaOps.Router.Transport.*.dll"))
{
var report = await pluginLoader.LoadFromSignedManifestDirectoryAsync(
bundlePath,
validator,
trustRoot,
transportPolicy,
cancellationToken);
if (!report.IsAccepted)
{
throw new InvalidOperationException(report.RejectionReason);
}
}
// Register the configured transport from the admitted signed bundle.
var plugin = pluginLoader.GetPlugin("messaging");
plugin?.Register(new RouterTransportRegistrationContext(
builder.Services,
builder.Configuration,
RouterTransportMode.Server));
var app = builder.Build();
// ...
Gateway Integration
The Gateway automatically loads transport plugins during startup. Configure in router.yaml:
gateway:
name: api-gateway
plugins:
transports:
directory: plugins/router/transports
searchPattern: "StellaOps.Router.Transport.*.dll"
Creating Custom Transports
See the Transport Plugin Development Guide for creating custom transport implementations.
Minimal Plugin Example
using StellaOps.Router.Common.Plugins;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
namespace MyCompany.Router.Transport.Custom;
public sealed class CustomTransportPlugin : IRouterTransportPlugin
{
public string TransportName => "custom";
public string DisplayName => "Custom Transport";
public bool IsAvailable(IServiceProvider services) => true;
public void Register(RouterTransportRegistrationContext context)
{
var configSection = context.Configuration.GetSection("Router:Transport:Custom");
context.Services.Configure<CustomTransportOptions>(options =>
{
configSection.Bind(options);
});
if (context.Mode.HasFlag(RouterTransportMode.Server))
{
context.Services.AddSingleton<CustomTransportServer>();
context.Services.AddSingleton<ITransportServer>(sp =>
sp.GetRequiredService<CustomTransportServer>());
}
if (context.Mode.HasFlag(RouterTransportMode.Client))
{
context.Services.AddSingleton<CustomTransportClient>();
context.Services.AddSingleton<ITransportClient>(sp =>
sp.GetRequiredService<CustomTransportClient>());
context.Services.AddSingleton<IMicroserviceTransport>(sp =>
sp.GetRequiredService<CustomTransportClient>());
}
}
}
Transport Selection Guide
| Scenario | Recommended Transport | Configuration |
|---|---|---|
| Development/Testing | InMemory | Type: inmemory |
| Same-datacenter | TCP | Type: tcp |
| Cross-datacenter secure | TLS | Type: tls with mTLS |
| High-volume async | RabbitMQ | Type: rabbitmq |
| Broadcast/fire-and-forget | UDP | Type: udp |
| Distributed with replay | Valkey | Via Messaging plugins |
| Transactional messaging | PostgreSQL | Via Messaging plugins |
Air-Gap Deployment
For offline/air-gapped deployments:
- Pre-package transport plugins with your deployment
- Configure the plugin directory path
- No external network access required
gateway:
plugins:
transports:
directory: /opt/stellaops/plugins/router/transports
See Also
- Router Architecture
- Plugin SDK Guide
- Unified Plugin System
