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.
Newest first, grouped by year. Search or filter by topic.
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.
DShop.Common's Consul registry tracks which service instances it has used to spread load evenly - then registers as transient, discarding that memory on nearly every request.
KC Star V5 gives the sales star a sibling: a full organizational hierarchy — organisation, regions, offices, personnel — with its own dimension rows, its own fact rows, and its own SCD2. Kicking off the series on the version where one star became three.
DShop runs a whole SignalR service to push operation results to the browser in real time - JWT handshake, per-user groups, Redis backplane. No frontend connects to it, and both UIs sleep through eventual consistency instead.
The storage catalog entry is really five templates over one base module - blob, file, queue, table and static website - and the least-used wrapper is where every copy-paste defect in the estate went to hide.
Every FastEndpoints route is mapped as a Minimal API whose handler returns the same singleton IResult - and that one weird trick is the door into the whole per-request pipeline. Part 3 of FastEndpoints in Depth.
Storage subscribes to almost every event in DShop, serves read-only queries, and owns nothing it cannot rebuild - the read side of a CQRS split that runs across a service boundary instead of inside one. Part 10 of Nine Services and a Message Bus.
Through V3, KC Star assumed every number it was fed was true. V4 stops assuming - adding data quality scores, lineage, and performance monitoring so the warehouse can say how much it trusts its own data. Kicking off the data governance series.
DShop.Common picks client-side discovery, a router, or a static address from one word in JSON - and self-registers each service into Consul with a heartbeat lease.
A signup click becomes a real PostgreSQL database or schema in seconds. Running CREATE DATABASE from application code feels illegal until you contain it — identifier validation, quoted DDL, idempotent steps, and a status machine that admits when provisioning fails.
DShop puts all its authorization at the gateway and none in the services behind it - then publishes every service port to the host. The compose file quietly defeats the entire security model.
KC Star V2 leaked aggregate rows because base facts and rollups shared one table. V3 gives aggregates a dedicated SalesAggregationFact table with its own SCD2 - and the fix is as much about what SalesFact loses as what the new table gains.
DShop runs competing consumers over an at-least-once bus with no message-id dedup, so a redelivered reservation decrements stock twice - the estate aspires to idempotency and enforces none of it. Part 9 of Nine Services and a Message Bus.
Azure Functions want their key in an x-functions-key header; Logic App workflows want a SAS signature in the query string. How a discovery record's type field became a calling-convention discriminator, and how one small HTTP service hid that difference from every caller in the estate. Part 3 of Service Discovery Without a Service Mesh.
KC Star V1 declared eight measures and computed four. V2 computes all eight - base measures and aggregates together in a single SalesFact table. Kicking off the series on the version that made the warehouse analytical, and started the trouble that V3 had to fix.
A reusable try-catch-finally wrapper in DShop.Common awaits a null-conditional delegate - so the success path throws a NullReferenceException the failure path avoids.
Nine thin custom Terraform modules carried the entire platform-integration story of an Azure estate. This part dissects the APIM-publication half - key minting through local-exec, SAS-splitting through PowerShell, twin modules one hyphen apart, and a typo frozen into dozens of source strings. Part 5 of the Terraform on Azure series.
DShop's gateway answers a write with 202 Accepted and a header pointing at an operation that hasn't happened yet. Reading the contract shows a clean async-REST design - and two small bugs that undercut it.
A walk through Pactify's PactMaker fluent API - the two-interface builder trick that hides Build() from you, why the consumer test always passes, and the uninitialized-object surprise inside WithBody<T>().
Operations subscribes to every command and event in the estate by reflection and routes them through two open-generic handlers - a neat trick with one dead limb the wiring can never light. Part 8 of Nine Services and a Message Bus.
What if dimensions and measures were rows instead of columns? Introducing KC Star, a PostgreSQL data warehouse I evolved through nine versions, starting with the inverted foundation - SCD2 history, SHA-256 fingerprints and time travel included.
DShop.Common ships its own in-process command and query dispatch - marker interfaces, a handler triple, and one dynamic double-dispatch standing in for a library.
The storage design behind ArchiveKit - typed queryable columns and a jsonb payload from a single write, why the archive's EntityId is an index but deliberately not a foreign key, and the reflective model configuration that builds every archive table from one method call. Part 4 of the Archive-on-Delete with ArchiveKit series.
DShop.Api.Next rebuilds the whole code-first gateway as Ntrada configuration - a 17-line Program.cs and a folder of YAML. Reading both side by side shows exactly what you trade when a gateway becomes data.
FeedR's API gateway is a YARP reverse proxy whose entire routing table lives in appsettings.json - prefix-stripping routes, per-environment cluster overrides, and a one-line transform that starts every distributed trace. Part 2 of the FeedR deep dive.