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 10.0
  • Install the required packages:
    dotnet add package Excalibur.Dispatch
    dotnet add package Excalibur.Hosting
  • 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(sql => sql.ConnectionString(connectionString)))
.AddCdc(cdc => cdc.TrackTable<Order>())
.AddSagas(saga => saga.WithCoordination().WithTimeouts())
.AddLeaderElection(le => le
.UseSqlServer(sql => sql.ConnectionString(connectionString))
.WithOptions(o => o.LeaseDuration = TimeSpan.FromSeconds(30)));
});

AddExcalibur() is provided by Excalibur.Hosting, while each .AddXxx(...) subsystem method is provided by its feature package.

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
Unified builder (AddExcalibur)Excalibur.Hosting
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(sql => sql.ConnectionString(connectionString))
.EnableBackgroundProcessing()
.WithProcessing(p => p.BatchSize(100));
});

// Change data capture for projections
excalibur.AddCdc(cdc =>
{
cdc.UseSqlServer(sql => sql.ConnectionString(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.UseObservability();
dispatch.ConfigurePipeline("default", p => p.UseValidation());
});

// 2. Configure Excalibur subsystems
services.AddExcalibur(excalibur =>
{
excalibur
.AddEventSourcing(es => es.UseEventStore<SqlServerEventStore>())
.AddOutbox(outbox => outbox.UseSqlServer(sql => sql.ConnectionString(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(opts => opts.ConnectionString(connectionString));
});
});

Configuration Sections​

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

Application identity​

ConfigureApplicationContext() establishes who your application is. Two values are required:

KeyMeaningDefault when unset
ApplicationNameThe application's display identityThe host environment's application name — your entry assembly, unless the host was told otherwise
ApplicationSystemNameThe machine-readable identity used in URLs, cache keys and stored recordsApplicationName in kebab-case

Both have defaults, so a host that configures nothing still starts. Set them explicitly when the defaults are not what you want to live with — and for ApplicationName in particular, because it is written into authorization grant records, where a value derived from an assembly name is rarely the one you would choose.

{
"ApplicationContext": {
"ApplicationName": "Order Management",
"ApplicationSystemName": "order-management"
}
}

A value you supply always wins; only blank values are filled in. The section is bound to IOptions<ApplicationContextOptions> and validated at startup, so a value that is present but empty fails immediately rather than surfacing later as a blank field in a log, a telemetry dimension, or a stored grant.

Upgrading from 3.x

Startup validation of these two values is new. An application that previously ran with a blank ApplicationName was not working correctly — it was writing that blank into every record that carries it. If your host fails to start naming these fields, set them, or accept the defaults above.

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​