Skip to main content
Version: Next

Reliability Patterns

Hermodr provides a comprehensive set of reliability patterns that ensure your domain events are delivered reliably, tracked accurately, and can be recovered in case of failures.

Why Reliability Matters

In distributed systems, publishing an event is rarely as simple as calling a method. Network failures, broker outages, serialization errors, and resource constraints can all cause event delivery to fail. The reliability patterns in Hermodr address these challenges:

PatternProblem SolvedWhen to Use
Transactional OutboxPrevents event loss when the broker is unavailableWhen you need atomic commits between business data and event publication
Dead-Letter HandlingCaptures failed deliveries for later recoveryWhen transient failures must not result in permanent event loss
Delivery LogProvides operational visibility into publish healthWhen you need to monitor delivery success rates, latency, and troubleshoot issues
Audit TrailCreates an immutable record of all published eventsFor compliance, auditing, and reconstructing event history

Architecture Overview

┌────────────────────────────────────────────────────────────────────┐
│ EventPublisher Pipeline │
│ │
│ ┌──────────────┐ ┌────────────────────────────────┐ │
│ │ Event Data │─────▶│ Middleware Pipeline │ │
│ └──────────────┘ └───────────────┬────────────────┘ │
│ │ │
│ ┌──────────────────────────┼───────────────────┐ │
│ │ │ │ │
│ ┌────────▼────────┐ ┌────────────▼──────┐ ┌─────────▼────┐ │
│ │ Outbox Channel │ │ Delivery Log │ │ Audit │ │
│ │ (durability) │ │ (telemetry) │ │ Trail │ │
│ └────────┬────────┘ └───────────────────┘ └──────────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ Relay Service │ │
│ │ (async send) │ │
│ └────────┬────────┘ │
│ │ │
│ ┌────────▼────────┐ │
│ │ Dead-Letter │ │
│ │ (failure capture) │
│ └─────────────────┘ │
└────────────────────────────────────────────────────────────────────┘

Pattern Selection Guide

ScenarioRecommended PatternKey Benefit
Broker is unavailable at publish timeTransactional OutboxAtomic commits between business data and events
Transient failures cause message lossDead-Letter HandlingAutomatic retry and failure recovery
Need to monitor delivery healthDelivery LogTrack success rates, latency, and troubleshoot
Compliance requires immutable audit trailAudit TrailComplete, tamper-proof event history
Need maximum reliabilityAll patterns combinedDurability + telemetry + recovery + compliance

Combining Patterns

The patterns are designed to work together:

PatternRole in Combined Stack
OutboxEnsures durability — events persisted atomically with business data
Delivery LogTracks every attempt — success, failure, retries, latency
Dead-LetterCaptures failures — automatic retry and recovery
Audit TrailMaintains history — immutable record for compliance

Common Combinations

Maximum Reliability Stack

builder.Services
.AddEventPublisher()
// Durability: persist events atomically with business data
.AddEntityFrameworkOutbox(opts => opts.UseSqlServer(connectionString))
.WithRelay()
// Telemetry: track every delivery attempt
.AddDeliveryLog(log => log.UseEntityFramework(opts =>
opts.UseSqlServer(connectionString)))
// Recovery: capture and retry failed deliveries
.AddDeadLetter()
.WithEntityFramework(opts => opts.UseSqlServer(connectionString))
.WithReplayWorker()
// Audit: maintain immutable event history
.AddAuditTrail(audit => audit.UseNDJson(options =>
options.DirectoryPath = "/var/audit"));

Lightweight Monitoring

builder.Services
.AddEventPublisher()
// Just track delivery attempts
.AddDeliveryLog(log => log.UseInMemory());

Compliance-First

builder.Services
.AddEventPublisher()
// Audit trail for compliance
.AddAuditTrail(audit => audit.UseNDJson(options =>
{
options.DirectoryPath = "/secure/audit";
options.MaxFileCount = 365; // Keep 1 year
}))
// Delivery log for operational visibility
.AddDeliveryLog(log => log.UseEntityFramework(opts =>
opts.UseSqlServer(connectionString)));