Elarion

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 }
  }
}
KeyDefaultEffect
Modules:{Name}:EnabledtrueDisables 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
  }
}
KeyDefaultEffect
Scheduler:EnabledtrueMaster 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:MaxConcurrentExecutionsimplementation defaultGlobal cap on concurrent job executions.
Scheduler:MaxRetainedCompletedJobsimplementation defaultHow many terminal job states are kept in memory.
Scheduler:MaxMisfireCatchUpRunsimplementation defaultUpper 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:

PlaceholderBehavior
${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.

SectionRead byEffect
FeatureManagementAddElarionFeatureManagement(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:

PropertyDefaultPurpose
ElarionJsonRpcGenerateSchemafalseEnables the build-time export targets.
ElarionJsonRpcGenerateSchemaOnBuildsame as aboveControls automatic generation during dotnet build.
ElarionJsonRpcSchemaOutputPath$(BaseIntermediateOutputPath)rpc-schema.jsonExact output file path.
ElarionJsonRpcSchemaOutputDirectory$(BaseIntermediateOutputPath)Output directory (with …FileName).
ElarionJsonRpcSchemaFileNamerpc-schema.jsonOutput file name.
ElarionJsonRpcSchemaEnvironmentDevelopmentEnvironment used while loading the app.
ElarionJsonRpcSchemaApplicationArgumentsemptyArgs passed to the app entry point.
ElarionJsonRpcSchemaGenerationOptionsemptyExtra tool arguments.

See Schema generation.

Current user (options, not config)

AddElarionCurrentUser(options => …) configures claim mapping in code rather than appsettings:

OptionDefault
UserIdClaimType"sub"
EmailClaimType"email"
RoleClaimTypeClaimTypes.Role
DefaultRolesWhenAuthenticatedempty

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:

OptionDefault
PollingInterval1 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:

OptionDefault
RunDeliveryWorkertrue (false disables claiming only; publishers still require the complete generated consumer catalog for fan-out/role resolution)
PollingInterval1 second
BatchSize100
MaxDeliveryAttempts10
LeaseDuration2 minutes
BaseRetryDelay5 seconds (exponential backoff base; Zero retries on the next poll)
MaxRetryDelay1 hour
RetentionPeriod7 days (null keeps delivered rows forever)
PurgeInterval1 hour (how often the worker runs the retention purge)
SerializerOptionsnull (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
});
OptionDefault
PropertyNamingPolicyJsonNamingPolicy.CamelCase
PropertyNameCaseInsensitivetrue
DefaultIgnoreConditionWhenWritingNull
EnableReflectionFallbackfalse (AOT-strict; a type missing from every source-gen context throws)
TypeInfoResolversTransport envelope + module contexts, composed first-match-wins
OverrideTypeInfoResolversempty (host-priority resolvers composed ahead of every TypeInfoResolvers entry — the way to override a type a transport envelope context also registers)
PostConfigurenone (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();
OptionDefault
MaxDepth32 (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
OptionDefault
Enabledtrue (the built-in user enricher runs; host-registered enrichers are unaffected)
IncludeRolestrue (emit user.roles / UserRoles)
IncludePermissionstrue (emit user.permissions / UserPermissions from the permission claim type)
IncludeEmailfalse (email is PII — opt in to emit user.email / UserEmail)
MaxItems16 (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));
OptionDefault
DefaultInvokeTimeout30 seconds (applied whenever an InvokeAsync call carries no per-call ClientInvokeOptions.Timeout; null = no default — the call is bounded only by its token)
MaxIdentityMetadataEntries32 (adapter-owned identity metadata entries accepted at registration or promotion)
MaxIdentityMetadataKeyLength128 (UTF-16 chars per metadata key)
MaxIdentityMetadataValueLength1024 (UTF-16 chars per metadata value)
MaxPrincipalIdentities16 (identities per connection principal)
MaxPrincipalClaims256 (claims across the principal and every actor identity)
MaxPrincipalActorDepth16 (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:

OptionDefault
Framerrequired (LengthPrefixedTcpFramer, DelimitedTcpFramer, or custom)
MaxInboundFrameBytes1 MiB (total unconsumed wire bytes per inbound frame — prefix/header/body/trailer included)
MaxOutboundFrameBytes1 MiB (total framed wire bytes per outbound message)
InitialReadBufferBytes / InitialSendBufferBytes8 KiB / 4 KiB (send buffer is pooled and trimmed after oversized frames)
MaxPendingSends256 (bounded outbound admission — queued plus in-progress; at capacity a send throws TcpSendQueueFullException)
ShutdownGracePeriod5 seconds (graceful-close drain window before stragglers are force-aborted; shutdown then awaits every connection task)
HandshakeTimeout10 seconds (framed application authentication deadline)
Tlsnull (TcpServerTlsOptions on listeners / TcpClientTlsOptions on dialers; own HandshakeTimeout default 10 s; TLS always completes before framing)
IdleTimeoutnull (arms the codec's OnIdleAsync)
NoDelaytrue
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)

On this page