Middleware Pipeline¶
This page explains how the MiddlewarePipeline fits into the Nalix request path and how to leverage it for application-level policy and observability.
The Middleware Model¶
Nalix utilizes a single, high-performance middleware layer powered by the MiddlewarePipeline. This pipeline executes after packet deserialization and metadata resolution, giving you full context for every request.
flowchart LR
A["Socket frame"] --> B["FramePipeline (Low-level)"]
B --> C["Deserialize packet"]
C --> D["Resolve handler metadata"]
D --> E["MiddlewarePipeline"]
E --> F["Handler"]
F --> G["Return handler / reply"]
Middleware Pipeline¶
The MiddlewarePipeline runs with the full packet execution context. Middleware usually consumes that state through IPacketContext<TPacket>, while the runtime backs it with a pooled PacketContext<TPacket> instance carrying the deserialized packet, connection state, and cached handler metadata.
Use it when:
- You need permission checks
- You need timeout enforcement
- You need rate limiting or concurrency limiting
- You need audit logging with handler context
- You need tenant or product policy checks
Tradeoff: Because it runs after deserialization, the packet has already been allocated. For early-stage rejection of malformed traffic, rely on ConnectionGuard or Protocol validation.
Low-Level Transformations¶
Low-level buffer operations such as decryption, decompression, and raw frame validation are integrated into the FramePipeline. This pipeline is executed directly by the Listeners (TCP/UDP) at the transport layer before the packet reaches runtime middleware.
Execution Order¶
Middleware ordering is attribute-driven, not raw registration order. The pipeline reads
MiddlewareOrderAttribute and MiddlewareStageAttribute from each middleware type.
If MiddlewareOrderAttribute is absent, the order defaults to 0. If
MiddlewareStageAttribute is absent, the stage defaults to Inbound.
| Stage bucket | Source behavior |
|---|---|
| Inbound | Sorted by MiddlewareOrder ascending. |
| Outbound | Sorted by MiddlewareOrder descending. |
Outbound with AlwaysExecute=true |
Stored in a separate outbound-always bucket, sorted descending, and executed after the handler even when normal outbound is skipped. |
flowchart LR
I1["Inbound low order"] --> I2["Inbound high order"]
I2 --> H["Handler"]
H --> A1["Outbound Always high order"]
A1 --> O1["Outbound high order"]
O1 --> O2["Outbound low order"]
Registration example:
PacketDispatchChannel dispatch = new(options =>
{
// Register middleware into the MiddlewarePipeline
options.WithMiddleware(new PermissionMiddleware());
options.WithMiddleware(new RateLimitMiddleware());
options.WithMiddleware(new AuditMiddleware());
});
How Metadata Fits In¶
Middleware becomes powerful because the dispatcher resolves metadata before the pipeline runs.
Middleware can read:
PacketOpcode— the handler's opcode- Permission rules (
[PacketPermission]) - Timeout rules (
[PacketTimeout]) - Rate limit rules (
[PacketRateLimit]) - Concurrency limits (
[PacketConcurrencyLimit]) - Custom attributes added by
IPacketMetadataProvider
The typical flow is:
- Declare attributes on handler methods
- Optionally enrich them with
IPacketMetadataProvider - Read the resolved metadata inside middleware via
context.Attributes
Decision Guide¶
| Need | Best fit |
|---|---|
| Reject a malformed frame before packet creation | Protocol / ConnectionGuard |
| Decrypt or decompress a frame | FramePipeline (Transport) |
| Block a packet by permission level | MiddlewarePipeline |
| Apply per-handler timeout rules | MiddlewarePipeline |
| Read a custom tenant tag from metadata | MiddlewarePipeline |
| Rate limit by opcode or endpoint | MiddlewarePipeline |
| Audit handler invocations | MiddlewarePipeline |
Common Pitfalls¶
Pitfall: Forgetting to call next()
If a middleware does not call await next(ct), the request pipeline is short-circuited. This is intentional for rejection scenarios but can cause silent drops if done accidentally.
Pitfall: Ordering assumptions
Middleware execution uses MiddlewareOrderAttribute, not insertion order. If multiple middleware share the same order value, their relative order should not be relied on.
See it in action¶
- Custom Middleware End-to-End — Create a custom middleware and metadata provider.
- UDP Auth Flow — See how authentication middleware is used in a real scenario.
- TCP Request/Response — Observe middleware in a standard TCP flow.