Configuration
Every configuration key and MSBuild property Elarion reads, in one place.
This page collects the runtime configuration sections and build properties Elarion reads. Most are optional with sensible defaults.
Modules
Feature modules are enabled by default. Disable one by name:
{
"Modules": {
"Clients": { "Enabled": false }
}
}| Key | Default | Effect |
|---|---|---|
Modules:{Name}:Enabled | true | Disables a feature module's handlers, endpoints, JSON metadata, and scheduled jobs. Ignored for core modules. |
See Modules.
Scheduler
Read by AddElarionScheduler(IConfiguration):
{
"Scheduler": {
"Enabled": true,
"MaxConcurrentExecutions": 8,
"MaxRetainedCompletedJobs": 1024,
"MaxMisfireCatchUpRuns": 32
}
}| Key | Default | Effect |
|---|---|---|
Scheduler:Enabled | true | Master switch for the in-memory scheduler. When false, descriptor-declared jobs are not enqueued and the runtime IJobScheduler enqueue/schedule APIs throw InvalidOperationException (a disabled instance never drains its queue). |
Scheduler:MaxConcurrentExecutions | implementation default | Global cap on concurrent job executions. |
Scheduler:MaxRetainedCompletedJobs | implementation default | How many terminal job states are kept in memory. |
Scheduler:MaxMisfireCatchUpRuns | implementation default | Upper bound on catch-up runs for the CatchUp misfire policy. |
See Scheduling.
Scheduled job placeholders
[ScheduledJob] string properties (FixedRate, FixedDelay, Cron, Enabled, …) support
Spring-style configuration placeholders, re-resolved per occurrence:
| Placeholder | Behavior |
|---|---|
${Jobs:Interval} | Resolve the key; throw during resolution if missing. |
${Jobs:Interval:-15m} | Resolve the key; fall back to 15m if missing or blank. |
See Schedules.
Feature flags
[FeatureGate] and [FeatureVariant] evaluate against the IFeatureFlagService seam. Where the flag values
come from depends on which provider package the host wires.
Batteries-included config-driven flags
AddElarionFeatureManagement(IConfiguration) (from Elarion.FeatureFlags.FeatureManagement) wires the
Microsoft.FeatureManagement OpenFeature provider behind the OpenFeature-backed IFeatureFlagService, so
[FeatureGate]/[FeatureVariant] read flags out of the conventional FeatureManagement configuration section:
{
"FeatureManagement": {
"BetaCheckout": true,
"PricingExperiment": {
"Variants": [
{ "Name": "control", "ConfigurationValue": "control" },
{ "Name": "treatment", "ConfigurationValue": "treatment" }
],
"Allocation": {
"DefaultWhenEnabled": "control",
"Percentile": [
{ "Variant": "treatment", "From": 0, "To": 50 },
{ "Variant": "control", "From": 50, "To": 100 }
]
},
"EnabledFor": [ { "Name": "AlwaysOn" } ]
}
}
}BetaCheckout is a boolean gate (drives a [FeatureGate("BetaCheckout")]); PricingExperiment is a variant
flag whose allocated variant selects a [FeatureVariant("PricingExperiment", Variant = "treatment")]
implementation.
| Section | Read by | Effect |
|---|---|---|
FeatureManagement | AddElarionFeatureManagement(configuration) | Standard Microsoft.FeatureManagement schema (booleans, filters, variants/allocations) surfaced to [FeatureGate]/[FeatureVariant]. |
Bring-your-own provider
AddElarionOpenFeature() (from Elarion.FeatureFlags.OpenFeature) registers the default OpenFeature-backed
IFeatureFlagService/IFeatureVariantService and takes its flag values from whatever OpenFeature provider the
host registers separately (services.AddOpenFeature(b => b.AddProvider(...)) — LaunchDarkly, ConfigCat, flagd,
Flagsmith, …), not from an Elarion-owned config section. It maps ICurrentUser into the OpenFeature
EvaluationContext off-HTTP (targeting key plus the user id / groups), so per-user targeting works under
JSON-RPC, MCP, and HTTP alike. Configure the provider per its own documentation.
See Feature flags.
JSON-RPC schema generation (MSBuild)
Properties read by Elarion.AspNetCore.SchemaGeneration during build:
| Property | Default | Purpose |
|---|---|---|
ElarionJsonRpcGenerateSchema | false | Enables the build-time export targets. |
ElarionJsonRpcGenerateSchemaOnBuild | same as above | Controls automatic generation during dotnet build. |
ElarionJsonRpcSchemaOutputPath | $(BaseIntermediateOutputPath)rpc-schema.json | Exact output file path. |
ElarionJsonRpcSchemaOutputDirectory | $(BaseIntermediateOutputPath) | Output directory (with …FileName). |
ElarionJsonRpcSchemaFileName | rpc-schema.json | Output file name. |
ElarionJsonRpcSchemaEnvironment | Development | Environment used while loading the app. |
ElarionJsonRpcSchemaApplicationArguments | empty | Args passed to the app entry point. |
ElarionJsonRpcSchemaGenerationOptions | empty | Extra tool arguments. |
See Schema generation.
Current user (options, not config)
AddElarionCurrentUser(options => …) configures claim mapping in code rather than appsettings:
| Option | Default |
|---|---|
UserIdClaimType | "sub" |
EmailClaimType | "email" |
RoleClaimType | ClaimTypes.Role |
DefaultRolesWhenAuthenticated | empty |
See Current user.
Idempotency purge (options, not config)
AddElarionIdempotencyEntityFrameworkCore<TDbContext>(configure => …) takes an optional
Action<IdempotencyPurgeOptions> configured in code rather than appsettings. It tunes the background
IdempotencyKeyPurgeService that reclaims expired keys:
| Option | Default |
|---|---|
PollingInterval | 1 hour |
Complementary to the per-handler [Idempotent(RetentionHours = …)], which sets how long a completed key is
retained; PollingInterval sets how often the worker sweeps out keys past that retention.
See Idempotency.
Outbox (options, not config)
AddElarionOutbox<TDbContext>(configure => …) (from Elarion.Messaging.Outbox) takes an optional
Action<OutboxOptions> configured in code rather than appsettings. It tunes the durable integration-event
tier and its background OutboxDeliveryService:
| Option | Default |
|---|---|
RunDeliveryWorker | true (false disables claiming only; publishers still require the complete generated consumer catalog for fan-out/role resolution) |
PollingInterval | 1 second |
BatchSize | 100 |
MaxDeliveryAttempts | 10 |
LeaseDuration | 2 minutes |
BaseRetryDelay | 5 seconds (exponential backoff base; Zero retries on the next poll) |
MaxRetryDelay | 1 hour |
RetentionPeriod | 7 days (null keeps delivered rows forever) |
PurgeInterval | 1 hour (how often the worker runs the retention purge) |
SerializerOptions | null (canonical IElarionJsonSerialization) |
See Event backends.
JSON serialization (options, not config)
Every subsystem shares one canonical JsonSerializerOptions, configured in code (not appsettings) via
ConfigureElarionJson(Action<ElarionJsonOptions>). AddElarion(configuration) already contributes every
enabled module's source-generated context, so most hosts configure nothing:
builder.Services.ConfigureElarionJson(o => {
o.PropertyNamingPolicy = JsonNamingPolicy.SnakeCaseLower; // default: CamelCase
o.TypeInfoResolvers.Add(SomeExtraContext.Default); // an extra source-gen context
});| Option | Default |
|---|---|
PropertyNamingPolicy | JsonNamingPolicy.CamelCase |
PropertyNameCaseInsensitive | true |
DefaultIgnoreCondition | WhenWritingNull |
EnableReflectionFallback | false (AOT-strict; a type missing from every source-gen context throws) |
TypeInfoResolvers | Transport envelope + module contexts, composed first-match-wins |
OverrideTypeInfoResolvers | empty (host-priority resolvers composed ahead of every TypeInfoResolvers entry — the way to override a type a transport envelope context also registers) |
PostConfigure | none (escape hatch for converters/encoder) |
See Serialization.
Request validation (options, not config)
AddElarionValidation(configure => …) (from Elarion.Validation) registers the default
IRequestValidator over Microsoft.Extensions.Validation and takes an optional
Action<ValidationOptions> configured in code rather than appsettings. It also calls
AddElarionJson(); the generated per-module validation resolvers register themselves through each
module's ConfigureDefaultServices, so most hosts pass nothing:
builder.Services.AddElarionValidation();| Option | Default |
|---|---|
MaxDepth | 32 (cycle protection when walking the request object graph) |
See Validation.
Handler context enrichment (options, not config)
Every handler is wrapped in a context-enrichment decorator that is on by default — it needs no
registration. AddElarionUserContextEnrichment(configure => …) (from Elarion) takes an optional
Action<UserContextEnrichmentOptions> configured in code rather than appsettings; call it only to
narrow the payload, opt into email, or disable the built-in user enricher:
// on by default — nothing to register; call only to change the defaults
builder.Services.AddElarionUserContextEnrichment(o => o.IncludeEmail = true); // opt into user.email (PII)
builder.Services.AddElarionUserContextEnrichment(o => o.Enabled = false); // disable the built-in user enricher| Option | Default |
|---|---|
Enabled | true (the built-in user enricher runs; host-registered enrichers are unaffected) |
IncludeRoles | true (emit user.roles / UserRoles) |
IncludePermissions | true (emit user.permissions / UserPermissions from the permission claim type) |
IncludeEmail | false (email is PII — opt in to emit user.email / UserEmail) |
MaxItems | 16 (upper bound on roles/permissions joined into a tag) |
Contribute your own trace tags / log-scope items by registering an IHandlerContextEnricher:
builder.Services.AddElarionHandlerContextEnricher<TenantContextEnricher>();The log-scope keys only surface if the host enables IncludeScopes on its logging exporter. See
Telemetry & observability › User & request context.
Connections (options, not config)
AddElarionConnections(options => …) (from Elarion.Connections) takes an optional
Action<ElarionConnectionsOptions> configured in code rather than appsettings — kernel-wide behavior
every connection adapter applies identically (per-endpoint and per-connection knobs stay on the
adapters):
builder.Services.AddElarionConnections(o => o.DefaultInvokeTimeout = TimeSpan.FromSeconds(10));| Option | Default |
|---|---|
DefaultInvokeTimeout | 30 seconds (applied whenever an InvokeAsync call carries no per-call ClientInvokeOptions.Timeout; null = no default — the call is bounded only by its token) |
MaxIdentityMetadataEntries | 32 (adapter-owned identity metadata entries accepted at registration or promotion) |
MaxIdentityMetadataKeyLength | 128 (UTF-16 chars per metadata key) |
MaxIdentityMetadataValueLength | 1024 (UTF-16 chars per metadata value) |
MaxPrincipalIdentities | 16 (identities per connection principal) |
MaxPrincipalClaims | 256 (claims across the principal and every actor identity) |
MaxPrincipalActorDepth | 16 (actor-identity nesting depth) |
The layering is per-call Timeout > DefaultInvokeTimeout > unbounded; pass
Timeout.InfiniteTimeSpan per call to make a single invoke unbounded without touching the default. See
Connections.
TCP endpoints (options, not config)
Each AddElarionTcpConnectionListener/Dialer call (and each runtime Apply…) configures one
endpoint in code via ElarionTcpListenerOptions/ElarionTcpDialerOptions; per-connection overrides
come from the session's Settings returning TcpConnectionSettings:
| Option | Default |
|---|---|
Framer | required (LengthPrefixedTcpFramer, DelimitedTcpFramer, or custom) |
MaxInboundFrameBytes | 1 MiB (total unconsumed wire bytes per inbound frame — prefix/header/body/trailer included) |
MaxOutboundFrameBytes | 1 MiB (total framed wire bytes per outbound message) |
InitialReadBufferBytes / InitialSendBufferBytes | 8 KiB / 4 KiB (send buffer is pooled and trimmed after oversized frames) |
MaxPendingSends | 256 (bounded outbound admission — queued plus in-progress; at capacity a send throws TcpSendQueueFullException) |
ShutdownGracePeriod | 5 seconds (graceful-close drain window before stragglers are force-aborted; shutdown then awaits every connection task) |
HandshakeTimeout | 10 seconds (framed application authentication deadline) |
Tls | null (TcpServerTlsOptions on listeners / TcpClientTlsOptions on dialers; own HandshakeTimeout default 10 s; TLS always completes before framing) |
IdleTimeout | null (arms the codec's OnIdleAsync) |
NoDelay | true |
Transport | "tcp" (bounded telemetry tag) |
MaxConcurrentConnections (listener) | null (shed excess accepted sockets at the cap) |
ReconnectMinDelay / ReconnectMaxDelay (dialer) | 1 s / 30 s (jittered exponential backoff) |