Skip to content

ChronicleOptions Reference

ChronicleOptions is the root configuration class for all Chronicle .NET clients. All properties can be set in code via the configureOptions callback on AddCratisChronicle, and most can be bound directly from appsettings.json under the Cratis:Chronicle section.

There are three options classes that form an inheritance chain, each adding settings relevant to its hosting context:

ClassUsed byAdds
ChronicleOptionsAll clientsConnection, serialization, timeouts, TLS, auth
ChronicleClientOptionsWorker services, console appsEvent store name, namespace resolver type
ChronicleAspNetCoreOptionsASP.NET Core appsHTTP header–based namespace resolution

All bindable settings live under Cratis:Chronicle:

{
"Cratis": {
"Chronicle": {
"ConnectionString": "chronicle://localhost:35000",
"EventStore": "my-store",
"EnableEventTypeGenerationValidation": false,
"DefaultSinkTypeId": "SQL",
"ConnectTimeout": 5,
"AutoDiscoverAndRegister": true,
"MaxReceiveMessageSize": 104857600,
"MaxSendMessageSize": 104857600,
"ProgramIdentifier": "my-app",
"ClaimsBasedNamespaceResolverClaimType": "tenant_id",
"Tls": {
"CertificatePath": "/certs/client.pfx",
"CertificatePassword": "secret"
},
"Authentication": {
"Authority": "https://login.example.com"
}
}
}
}

Asks the Kernel to enforce strict migration chain validation when registering event types at generation 2 or higher. The value is forwarded as part of the registration request.

Typebool
Defaultfalse

Image restriction: This flag is only honoured by the development image of the Kernel. The production image always ignores it and validates unconditionally, regardless of what the client sends. This makes it impossible to accidentally skip migration chain validation in production even if the client has this flag set to false.

To opt in to strict validation during development (recommended once your event schemas are stable), set the flag to true:

using Microsoft.Extensions.Hosting;
public static class ChronicleOptionsEnableValidationRegistration
{
public static void Configure(string[] args)
{
var builder = Host.CreateApplicationBuilder(args);
builder.AddCratisChronicle(configureOptions: options =>
{
options.EnableEventTypeGenerationValidation = true;
});
}
}

View C# snippet source on GitHub

In appsettings.json: "EnableEventTypeGenerationValidation": true.

See Generation Validation for the full ruleset.

Controls event staging once a unit of work begins completing.

TypeUnitOfWorkLifecyclePolicy (Compatibility or Strict)
DefaultCompatibility

In appsettings.json: "UnitOfWorkLifecyclePolicy": "Strict" under Cratis:Chronicle. Strict rejects late staging; Compatibility keeps legacy enrollment behavior and reports late attempts. Strict will become the default in the next major release. See Staging after completion begins for commit, rollback, and disposal behavior.

The gRPC endpoint for Chronicle Server.

TypeChronicleConnectionString
DefaultDevelopment connection string (chronicle://localhost:35000 with default dev credentials)
using Microsoft.Extensions.Hosting;
public static class ChronicleOptionsConnectionStringRegistration
{
public static void Configure(string[] args)
{
var builder = Host.CreateApplicationBuilder(args);
builder.AddCratisChronicle(configureOptions: options =>
{
options.ConnectionString = "chronicle://myserver:35000";
});
}
}

View C# snippet source on GitHub

In appsettings.json: "ConnectionString": "chronicle://myserver:35000".

Timeout in seconds when establishing a connection to Chronicle Server.

Typeint
Default5

Controls whether Chronicle automatically discovers event types, projections, reactors, reducers, and other artifacts from loaded assemblies on startup.

Typebool
Defaulttrue

Set to false when using a custom IClientArtifactsProvider or when you want full manual control over what gets registered.

Skips the connect-time wire-compatibility check against the server.

Typebool
Defaultfalse

Use this only as a deliberate, temporary escape hatch — for example, when a client that has only gained capabilities since the server’s release is incorrectly refused by a server that cannot be redeployed to pick up a wire-compatibility fix. It does not make an incompatibility disappear; it silences every incompatibility the check would have caught, including a genuine one. The connection string’s skipCompatibilityCheck=true option asks for the same thing; either input is enough. See Server support: Compatibility check for the full explanation.

Controls which sink type is used when registering projections and reducers with the Kernel. Chronicle supports two built-in sink types:

ValueDescription
WellKnownSinkTypes.MongoDBStores read models in MongoDB (default)
WellKnownSinkTypes.SQLStores read models in a SQL database as JSON documents
TypeSinkTypeId
DefaultWellKnownSinkTypes.MongoDB

To use SQL as the storage backend for all read models:

using Microsoft.Extensions.Hosting;
using Cratis.Chronicle.Sinks;
public static class ChronicleOptionsSqlSinkRegistration
{
public static void Configure(string[] args)
{
var builder = Host.CreateApplicationBuilder(args);
builder.AddCratisChronicle(configureOptions: options =>
{
options.DefaultSinkTypeId = WellKnownSinkTypes.SQL;
});
}
}

View C# snippet source on GitHub

In appsettings.json:

{ "Cratis": { "Chronicle": { "DefaultSinkTypeId": "SQL" } } }

See Sinks for detailed guidance on storage backends.

MaxReceiveMessageSize / MaxSendMessageSize

Section titled “MaxReceiveMessageSize / MaxSendMessageSize”

Maximum gRPC message sizes in bytes. See gRPC Message Size for detailed guidance.

Typeint?
Default104857600 (100 MB)

A human-readable identifier for the running application. Included in root causation metadata to identify which program appended an event.

Typestring
Default"[N/A]"

The software version of the entry assembly, extracted from AssemblyInformationalVersion or AssemblyVersion. Included in root causation to track which build produced an event, and sent with every projection registration so the kernel can ignore a registration from an older version than the one it has stored. Set it with the Cratis:Chronicle:SoftwareVersion configuration key (environment variable Cratis__Chronicle__SoftwareVersion). See the registration lifecycle.

Typestring (semantic version)
DefaultResolved from the entry assembly at startup

The commit SHA of the entry assembly, extracted from the +commit part of AssemblyInformationalVersion. Included in root causation to track which commit produced an event.

Typestring
DefaultResolved from the entry assembly at startup

The JWT claim type used by ClaimsBasedNamespaceResolver when namespace resolution is configured via WithClaimsBasedNamespaceResolver.

Typestring
Default"tenant_id"

How registering the client’s artifacts is retried when the Kernel does not accept them.

TypeRegistrationRetryOptions
DefaultFive attempts, two seconds growing to thirty
Nested propertyTypeDefaultDescription
MaxAttemptsint5How many times registering all artifacts is attempted before the failure surfaces. 1 disables retrying
InitialDelayTimeSpan00:00:02Wait after the first failed attempt. Each further attempt doubles it, jittered
MaximumDelayTimeSpan00:00:30Upper bound for the wait between attempts

Registration runs on the way up, so a registration that fails takes the host with it. A Kernel that is merely busy — catching a newly added read model up over a large event log, say — answers late rather than wrongly, and a host that dies on that answer comes back and asks again, adding its whole registration to the queue it was already waiting on. Retrying in place lets the client wait out a busy Kernel instead. Registration is idempotent, so a retry costs the Kernel only the comparison it already does; a Kernel that is genuinely refusing the definitions keeps failing and the host still ends up down, just after the attempts are spent rather than on the first.

In appsettings.json:

{ "Cratis": { "Chronicle": { "RegistrationRetry": { "MaxAttempts": 10, "MaximumDelay": "00:01:00" } } } }

How the .NET client runs reactors.

Nested propertyTypeDefaultDescription
MaxConcurrentPartitionsintprocessor count, at most 8How many partitions of one reactor are handled at the same time. Batches for one partition always run in order. 1 handles one batch at a time, as before. Must be at least 1

Handlers for different partitions can run at the same time, so shared non-thread-safe services are at risk.

{ "Cratis": { "Chronicle": { "Reactors": { "MaxConcurrentPartitions": 4 } } } }

How the .NET client runs reducers.

Nested propertyTypeDefaultDescription
MaxConcurrentPartitionsintprocessor count, at most 8How many partitions of one reducer are handled at the same time. Batches for one partition always run in order. 1 handles one batch at a time, as before. Must be at least 1
{ "Cratis": { "Chronicle": { "Reducers": { "MaxConcurrentPartitions": 4 } } } }

Controls the .NET client’s check for likely artifact renames or moves before each foreground registration run. Background retries retain its findings without repeating snapshots or drift logs.

TypeArtifactIdentityDriftPolicy
DefaultWarn
ValuesWarn, Fail, Ignore

Warn logs findings and continues registering. Fail throws ArtifactIdentityDriftDetected before any artifacts are registered when Warning-level reactor or event type findings exist, without retrying. Information-level reducer and projection findings never fail registration. Ignore skips the check and its kernel calls. Snapshot failures never prevent registration, even with Fail; a failed subscription confirmation omits that reactor or reducer candidate. Projections skip confirmation because the kernel keeps them subscribed until registration retires them.

In appsettings.json:

{ "Cratis": { "Chronicle": { "ArtifactIdentityDrift": "Fail" } } }

Use Fail in CI or staging to investigate likely identity changes before deploying. This is a heuristic: rolling deployments can hide reactor or reducer renames, and unrelated same-named observers or same-shaped events can match. Projections are more prone to false positives because subscribed candidates are included; their findings remain informational. Event types cannot be removed to acknowledge a finding; preserve the old id or switch to Warn after reviewing an intentional new identity. See Discovery report and identity drift for findings, log levels, and limitations.

TLS certificate settings for the gRPC connection. TLS is active when both CertificatePath and CertificatePassword are set. See TLS for full details.

TypeTls
DefaultTLS disabled (no certificate configured)
Nested propertyTypeDescription
CertificatePathstring?Path to a PFX certificate file
CertificatePasswordstring?Password for the certificate file

Kernel delivery settings under Cratis:Chronicle:Occurrences. These settings do not change observer retry policy.

PropertyTypeDefaultBehavior
MaxInFlightint1Maximum live leases per trigger and scope; values below one use one
MaxAttemptsint10Quarantines exhausted work; zero permits unlimited attempts
BackoffDelayint1Initial failure retry delay in seconds; negative values use zero
ExponentialBackoffDelayFactorfloat2Multiplier per failed attempt; values below one use one
MaximumBackoffDelayint600Failure retry delay cap in seconds; negative values use zero

Lease duration is selected by the claim or renew request, not this section: zero or a negative value uses 60 seconds, and the maximum is 600 seconds. Claims return at most 1,000 occurrences and remain subject to MaxInFlight. Kernel time controls expiry and backoff. See occurrence delivery and receipts for ordering, quarantine and recovery.

OAuth/OIDC authority configuration. When Authority is not set, the Chronicle internal OAuth authority is used.

TypeAuthentication
DefaultInternal authority
Nested propertyTypeDescription
Authoritystring?OAuth/OIDC authority URL

ChronicleClientOptions extends ChronicleOptions and is used by worker services, console apps, and other non-web hosts via IHostApplicationBuilder.AddCratisChronicle.

The name of the event store the client connects to. Required.

TypeEventStoreName
Default(none — must be set)
{ "Cratis": { "Chronicle": { "EventStore": "my-store" } } }

The Type of the IEventStoreNamespaceResolver to use for resolving the event store namespace. When null, defaults to DefaultEventStoreNamespaceResolver at runtime, which always returns the default namespace.

TypeType?
Defaultnull → DefaultEventStoreNamespaceResolver

This is a structural dependency — it resolves a type reference and cannot be meaningfully set from appsettings.json. Set it in code via the configureOptions callback or via IChronicleBuilder.

ChronicleAspNetCoreOptions extends ChronicleClientOptions and is used by ASP.NET Core applications via WebApplicationBuilder.AddCratisChronicle. It defaults EventStoreNamespaceResolverType to HttpHeaderEventStoreNamespaceResolver.

The HTTP request header used to resolve the event store namespace on a per-request basis.

Typestring
Default"x-cratis-tenant-id"
{ "Cratis": { "Chronicle": { "NamespaceHttpHeader": "x-my-tenant" } } }

The Kernel’s Cratis.Chronicle.Configuration.ChronicleOptions.Webhooks is separate from the client options above. Set these keys under webhooks in the Kernel’s chronicle.json, or under Cratis:Chronicle:Webhooks in application configuration. Environment variable equivalents use Cratis__Chronicle__Webhooks__ followed by the key.

KeyDefaultPurpose
ValidationWarnLog violations during rollout; Enforce rejects them. Enforce is planned as the next major release’s default.
AllowInsecureHttpfalsePermit HTTP in Development. Ignored with a startup warning outside Development. Loopback HTTP is automatically permitted in Development.
AllowedHosts[]Exact receiver/OAuth hosts or wildcard subdomains such as *.example.com. In Enforce mode unlisted hosts are rejected; approving a host also permits its private addresses.
EventStoreAllowedHosts{}Map of event-store names to host arrays. An entry replaces the global array, including when empty. Requests without an event-store option use the global list.
TestTimeoutSeconds30Timeout for the registration reachability probe.

Webhook delivery uses one HTTP attempt at a time. The observer owns retries, a finite retry budget, and durable deadlines; the HTTP resilience pipeline has no retry strategy. RetryDelaySeconds is retained for compatibility but no longer controls delivery retries. Webhook retry policy is configured under Webhooks:Retry, independently of the global observer retry settings. Non-webhook observers retain their existing retry and quarantine defaults.

Webhooks:Retry keyDefaultPurpose
BackoffScheduleSeconds[1, 5, 30, 120, 600, 1800, 3600]Delays for successive failures; the last entry repeats. Setting it replaces the default schedule.
MaximumBackoffDelay3600Caps the delay in seconds, including bounded ±20% jitter.
MaxRetryAttempts0No attempt-count limit; a positive value adds a limit alongside the elapsed budget.
RetryBudget"1.00:00:00"Elapsed budget from the first persisted failure since quarantine was last cleared. Zero disables this limit.
QuarantineOnFailedPartitionCount5Pause the observer when this many partitions are parked. Zero disables this threshold.
QuarantineOnFailedPartitionPercentage0.5Pause at or above this fraction of distinct partitions in failure/resolution history. Zero disables this threshold.

Either exhausted retry limit parks the partition. Schedule deadlines and the first failure’s timestamp survive reactivation; jitter is not resampled. Valid receiver/circuit deferrals do not consume attempts or count toward quarantine. There is no automatic quarantined-observer probe scheduler yet; recovery requires operator action.

MaximumRetryAfterSeconds bounds receiver-provided Retry-After delays on 429 and 503 responses. Its default is 86400 seconds (24 hours). Invalid or expired headers fall back to the retry budget, without sleeping in the HTTP pipeline. A valid deferral and an open-circuit rejection do not consume retry attempts. See webhook delivery policy for configuration-error pauses, immediate 410 parking, and manual recovery.

For example, Cratis__Chronicle__Webhooks__Validation=Enforce enables blocking, and Cratis__Chronicle__Webhooks__AllowedHosts__0=hooks.example.com approves one host. OAuth authorities and discovered token endpoint hosts must also be approved. Cloud metadata addresses need explicit approval even in Warn. Redirects are rejected in both modes.

See Webhook target validation for rollout, Docker/tunnel examples, DNS/address restrictions, and the distinction between warnings and blocking.