Skip to main content

Configuration Overview

Excalibur uses Microsoft-style dependency injection with fluent builder patterns for configuration. This guide covers the unified configuration approach and common patterns.

Before You Start

  • .NET 8.0+ (or .NET 9/10 for latest features)
  • Install the required packages:
    dotnet add package Excalibur.Dispatch
  • Familiarity with dependency injection and core concepts

Unified Entry Point

The AddExcalibur() extension method is the primary entry point for configuring all Excalibur subsystems:

using Microsoft.Extensions.DependencyInjection;

services.AddExcalibur(excalibur =>
{
excalibur
.AddEventSourcing(es => es.UseEventStore<SqlServerEventStore>())
.AddOutbox(outbox => outbox.UseSqlServer(connectionString))
.AddCdc(cdc => cdc.TrackTable<Order>())
.AddSagas(opts => opts.EnableTimeouts = true)
.AddLeaderElection(opts => opts.LeaseDuration = TimeSpan.FromSeconds(30));
});

This automatically:

  • Registers Dispatch primitives (IDispatcher, IMessageBus, etc.)
  • Sets up the core pipeline with sensible defaults
  • Configures each subsystem you enable

Required NuGet Packages

FeaturePackage
Core domain modelingExcalibur.Domain
Event sourcingExcalibur.EventSourcing
SQL Server providerExcalibur.EventSourcing.SqlServer
PostgreSQL providerExcalibur.EventSourcing.Postgres
Outbox patternExcalibur.Outbox
CDC (Change Data Capture)Excalibur.Cdc
SagasExcalibur.Saga
Leader electionExcalibur.LeaderElection

Configuration Patterns

Minimal Configuration

For simple applications:

services.AddExcalibur(excalibur =>
{
excalibur.AddEventSourcing(es =>
{
es.UseEventStore<SqlServerEventStore>();
});
});

Production Configuration

For production applications with all features:

var connectionString = builder.Configuration.GetConnectionString("Database");

services.AddExcalibur(excalibur =>
{
// Event sourcing with snapshots
excalibur.AddEventSourcing(es =>
{
es.UseEventStore<SqlServerEventStore>()
.UseIntervalSnapshots(100)
.AddRepository<OrderAggregate, OrderId>();
});

// Reliable messaging via outbox
excalibur.AddOutbox(outbox =>
{
outbox.UseSqlServer(connectionString)
.EnableBackgroundProcessing()
.WithProcessing(p => p.BatchSize(100));
});

// Change data capture for projections
excalibur.AddCdc(cdc =>
{
cdc.UseSqlServer(connectionString)
.TrackTable<Order>()
.TrackTable<Customer>();
});
});

Advanced Dispatch Configuration

When you need custom Dispatch configuration (transports, middleware), configure Dispatch separately:

// 1. Configure Dispatch with transports and middleware
services.AddDispatch(dispatch =>
{
dispatch.UseRabbitMQ(rmq => rmq.HostName("localhost"));
dispatch.AddObservability();
dispatch.ConfigurePipeline("default", p => p.UseValidation());
});

// 2. Configure Excalibur subsystems
services.AddExcalibur(excalibur =>
{
excalibur
.AddEventSourcing(es => es.UseEventStore<SqlServerEventStore>())
.AddOutbox(outbox => outbox.UseSqlServer(connectionString));
});

Both orderings are safe because all Dispatch registrations use TryAdd internally.

Configuration Sources

From appsettings.json

{
"ConnectionStrings": {
"EventStore": "Server=localhost;Database=Events;..."
},
"Excalibur": {
"Outbox": {
"BatchSize": 100,
"PollingInterval": "00:00:05"
},
"Snapshots": {
"Interval": 100
}
}
}
services.AddExcalibur(excalibur =>
{
var config = builder.Configuration.GetSection("Excalibur");

excalibur.AddEventSourcing(es =>
{
es.UseEventStore<SqlServerEventStore>()
.UseIntervalSnapshots(config.GetValue<int>("Snapshots:Interval"));
});
});

From Environment Variables

var connectionString = Environment.GetEnvironmentVariable("DATABASE_URL")
?? builder.Configuration.GetConnectionString("Database");

services.AddExcalibur(excalibur =>
{
excalibur.AddEventSourcing(es =>
{
es.UseSqlServer(connectionString);
});
});

Configuration Sections

SectionDescriptionGuide
Event SourcingEvent stores, repositories, snapshotsEvent Store Setup
OutboxReliable messaging, processing optionsOutbox Setup
SnapshotsSnapshot strategies and triggersSnapshot Setup

Health Checks

Add health checks for all Excalibur components:

services.AddExcaliburHealthChecks(health =>
{
health.AddSqlServer(connectionString, name: "database")
.AddCheck<OutboxHealthCheck>("outbox");
});

app.MapHealthChecks("/.well-known/ready");

Validation

Configuration is validated at startup. Common validation errors:

ErrorCauseSolution
EventStore not configuredMissing UseEventStore<T>()Add event store configuration
Connection string is nullMissing connection stringCheck appsettings or env vars
Invalid batch sizeBatchSize <= 0Use positive batch size

Next Steps

See Also