Skip to content
Kumar Chandrachooda
Series

Sagas with Chronicle

In reading order.

  • 9 parts
  • ≈ 53 min total
  • 9 published
Part 1 09 Aug 2025 6 min read

The Transaction That Outlives the Request

Split one database into five services and the transaction you deleted does not disappear - it goes feral. On sagas, compensation, process managers, and Chronicle, the small open-source .NET library this series reads line by line.

Part 2 29 Aug 2025 5 min read

Two Interfaces and a Base Class

Chronicle's entire programming model is Saga<TData>, ISagaStartAction, and ISagaAction. Building a full order-fulfilment saga to learn what Complete() promises, what Reject() actually does, and why a saga can have more than one beginning.

Part 3 27 Sep 2025 5 min read

How a Message Finds Its Saga

Correlation is the part of the saga pattern that fails silently. SagaId, SagaContext, the Empty-context trap that starts a new saga per message, and the one-method override that routes messages by their own content.

Part 4 04 Nov 2025 6 min read

One Message, Many Sagas

services.AddChronicle() registers sagas you never mentioned, and one ProcessAsync call can run five of them in parallel. Inside Chronicle's Scrutor scan, the seeker's dedupe trick, and the ref-counted lock that serializes each saga id.

Part 5 11 Dec 2025 6 min read

Four Small Classes Run Every Saga

Seeker, initializer, processor, post-processor - Chronicle's whole runtime is four internal classes you can read in ten minutes. A source walk through the pipeline, including the gate that drops messages, the finally block that always persists, and the state that isn't as final as it looks.

Part 6 18 Jan 2026 6 min read

Compensation Is a Replay in Reverse

When a Chronicle saga rejects, the saga log is replayed backwards and every handled message gets its CompensateAsync called. Tracing both rejection paths through the source reveals a surprise - only one of them actually compensates - plus a ForEach that never awaits.

Part 7 21 Feb 2026 6 min read

Where a Saga Keeps Its Memory

Chronicle's persistence surface is two interfaces - a state repository and an append-only log - and the defaults behind AddChronicle() are two Lists. What the contracts really demand, why the in-memory implementations are sharper than they look, and how to write a provider that holds up.

Part 8 20 Mar 2026 6 min read

Reading the Redis and Mongo Providers

Chronicle ships two persistence integrations, and reading them against the contract is a masterclass in provider sharp edges: a Redis key built from Type.GetHashCode() that changes on every restart, a Mongo delete-then-insert, and messages that may not survive the round trip.

Part 9 07 Apr 2026 7 min read

When a Saga Library Is Overkill

Eight parts of source-reading later, the honest retrospective. What Chronicle gets right, the timeout-shaped hole at its centre, how it stacks up against MassTransit and NServiceBus and durable execution - and the cases where a status column beats every saga framework ever written.