| title | Installation |
|---|---|
| description | Install the ES.FX NuGet packages, understand package naming and Central Package Management, and stand up a working Ignite host. |
ES.FX ships as a set of independently consumable NuGet packages under the ES.FX.* prefix. Take only the layer you need: the framework-agnostic core, a focused Addition, the Hosting lifecycle wrapper, a standalone feature library, or the full Ignite bootstrap with one or more Sparks. This page covers where the packages come from, how to install them, and a minimal end-to-end Ignite host you can copy and run.
- .NET 10 SDK or newer. Every ES.FX library targets
net10.0. - An IDE or editor (Visual Studio, Rider, or VS Code with the C# Dev Kit).
- Docker is only needed if you run the ES.FX functional test suite (Testcontainers spins up real services). It is not required to consume the packages. See Testing.
ES.FX packages are published to two feeds:
- NuGet.org — the primary public feed. Nothing extra to configure; the default
nuget.orgsource resolvesES.FX.*out of the box. - GitHub Packages — the same releases are also pushed to the
emberstackGitHub Packages registry.
For almost every consumer, the default NuGet.org source is all you need.
Note
Only builds from main publish releases. The public ES.FX.* versions you install from NuGet.org are cut from main (versioned with GitVersion, tag prefix v).
Package names mirror the layer and the thing they wrap, so you can predict them:
| Layer | Package pattern | Example |
|---|---|---|
| Core primitives | ES.FX |
ES.FX |
| Addition (augments one third-party library) | ES.FX.Additions.{Library} |
ES.FX.Additions.FluentValidation |
| Hosting lifecycle | ES.FX.Hosting |
ES.FX.Hosting |
| Ignite bootstrap | ES.FX.Ignite |
ES.FX.Ignite |
| Spark (one integration for Ignite) | ES.FX.Ignite.{Provider} |
ES.FX.Ignite.StackExchange.Redis |
| Standalone feature library | ES.FX.{Feature} |
ES.FX.TransactionalOutbox |
Browse the full set on the Sparks catalog and the Additions catalog.
Install with the .NET CLI:
dotnet add package ES.FX.Hosting
dotnet add package ES.FX.Ignite
dotnet add package ES.FX.Additions.Serilog
dotnet add package ES.FX.Ignite.Serilog
dotnet add package ES.FX.Ignite.StackExchange.RedisOr add <PackageReference> items to your .csproj:
<ItemGroup>
<PackageReference Include="ES.FX.Hosting" Version="1.0.0" />
<PackageReference Include="ES.FX.Ignite" Version="1.0.0" />
<PackageReference Include="ES.FX.Additions.Serilog" Version="1.0.0" />
<PackageReference Include="ES.FX.Ignite.Serilog" Version="1.0.0" />
<PackageReference Include="ES.FX.Ignite.StackExchange.Redis" Version="1.0.0" />
</ItemGroup>Tip
Replace the Version values with the latest published versions from NuGet.org.
If your solution uses Central Package Management (CPM) — pinning every version in Directory.Packages.props — declare each version once there and omit the Version attribute on the <PackageReference>. ES.FX itself is built this way.
<!-- Directory.Packages.props -->
<Project>
<PropertyGroup>
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
</PropertyGroup>
<ItemGroup>
<PackageVersion Include="ES.FX.Hosting" Version="1.0.0" />
<PackageVersion Include="ES.FX.Ignite" Version="1.0.0" />
<PackageVersion Include="ES.FX.Additions.Serilog" Version="1.0.0" />
<PackageVersion Include="ES.FX.Ignite.Serilog" Version="1.0.0" />
<PackageVersion Include="ES.FX.Ignite.StackExchange.Redis" Version="1.0.0" />
</ItemGroup>
</Project><!-- Your .csproj — no Version attribute under CPM -->
<ItemGroup>
<PackageReference Include="ES.FX.Hosting" />
<PackageReference Include="ES.FX.Ignite" />
<PackageReference Include="ES.FX.Additions.Serilog" />
<PackageReference Include="ES.FX.Ignite.Serilog" />
<PackageReference Include="ES.FX.Ignite.StackExchange.Redis" />
</ItemGroup>See Conventions & build config for how ES.FX applies CPM across the repository.
Ignite is a two-phase bootstrap, and the recommended entry point wraps it in ProgramEntry for structured startup, logging, and graceful shutdown:
ProgramEntry.CreateBuilder(args).UseSerilog().Build().RunAsync(...)wrapsMainwith lifecycle handling.UseSerilog()comes fromES.FX.Additions.Serilog.- Inside the callback, create the host builder and call
builder.Ignite(...)— phase A, onIHostApplicationBuilder, beforeBuild(). - Register any Sparks (for example
builder.IgniteRedisClient()) betweenbuilder.Ignite(...)andbuilder.Build(). - After
Build(), callapp.Ignite()— phase B, on the builtIHost. For aWebApplicationthis also wires middleware and health-check endpoints.
Important
builder.Ignite(...) and app.Ignite() are distinct extensions on distinct types. Phase A configures the builder; phase B finalizes the built host. Web-only middleware in phase B runs only when the host is a WebApplication.
The following Program.cs is a complete, runnable API host that mirrors the ES.FX playground composition:
using ES.FX.Additions.Serilog.Lifetime;
using ES.FX.Hosting.Lifetime;
using ES.FX.Ignite.Hosting;
using ES.FX.Ignite.Serilog.Hosting;
using ES.FX.Ignite.StackExchange.Redis.Hosting;
using StackExchange.Redis;
return await ProgramEntry.CreateBuilder(args).UseSerilog().Build().RunAsync(async _ =>
{
var builder = WebApplication.CreateBuilder(args);
// Route logging through Serilog.
builder.Logging.ClearProviders();
builder.IgniteSerilog();
// Phase A: activate Ignite on the host builder.
builder.Ignite(settings =>
{
settings.AspNetCore.JsonStringEnumConverterEnabled = true;
});
// Add a Spark: registers a shared IConnectionMultiplexer with health checks and tracing.
builder.IgniteRedisClient();
var app = builder.Build();
// Phase B: finalize Ignite on the built host (middleware + health endpoints for WebApplication).
app.Ignite();
app.MapGet("/ping", async (IConnectionMultiplexer redis) =>
{
var pong = await redis.GetDatabase().PingAsync();
return Results.Ok(new { RoundTrip = pong.ToString() });
});
await app.RunAsync();
return 0;
});Note
A background worker or console host is identical except you call Host.CreateApplicationBuilder(args) instead of WebApplication.CreateBuilder(args). Both call builder.Ignite() and app.Ignite(); non-web hosts simply get no web middleware.
All ES.FX configuration lives under a rooted Ignite: section in appsettings.json. Ignite's own observability toggles bind under Ignite:Settings; each Spark reads its own sub-section (Redis reads Ignite:Redis). A minimal configuration for the host above:
{
"Ignite": {
"Redis": {
"ConnectionString": "localhost:6379"
}
}
}Important
Mind the split: a Spark's Options (service config, such as ConnectionString) bind at Ignite:Redis directly, while its Settings (observability toggles) bind at Ignite:Redis:Settings. See the Ignite configuration model for the full layout.
Restore, build, and run:
dotnet runWith the Redis Spark registered and app.Ignite() called, the host gives you out of the box:
- A shared
IConnectionMultiplexerin DI (injected into the/pingendpoint above). - Health-check endpoints — readiness (all checks) and liveness (checks tagged
"live"only). The Redis health check participates in readiness by default. - OpenTelemetry logging, metrics, and tracing, with HttpClient/ASP.NET Core instrumentation and a tracing source for Redis.
- HttpClient resilience and standardized ProblemDetails error responses.
- Quickstart — build your first Ignite app step by step.
- Core concepts — the Ignite two-phase model, Sparks, and Settings vs Options.
- Ignite overview — everything the bootstrap wires for you.
- Sparks catalog — plug in Redis, EF Core, Azure, and more.
- Redis client integration — the Spark used in this example.
- Application hosting —
ProgramEntryand the lifecycle wrapper. - Conventions & build config — Central Package Management in ES.FX.
- Ignite configuration model — the
Ignite:section and the:Settingssub-node.