Skip to content
kc@kumarChandrachooda.com:~$ cd /blog/archive && read --section="top" 0%
Archive

Every article

Newest first, grouped by year. Search or filter by topic.

  • 556 articles
  • 41 matching
.NET 16 Jun 2026

IQueryable In, OData Out

FastEndpoints.OData is ninety lines that bolt Microsoft's OData query engine onto a REPR endpoint - a sealed Configure(), a fake ParameterInfo, and an endpoint filter that fishes the response out of HttpContext.Items. Reading it is a masterclass in integrating with a framework through its narrowest seam. Part 7 of FastEndpoints — The Missing Chapters.

.NET 07 Dec 2025

Sixteen Concepts, Copied Once

When Postsale was carved out of Sales, sixteen types came with it - and every place the twins differ marks a decision the extraction forced, including one base class that stopped draining and a repository that silently depends on it.

.NET 06 Dec 2025

The ADR Said UTC and One Switch Unsaid It

A decision record mandates UTC everywhere and an IClock abstraction, and thirty files honour it - then one process-global AppContext switch in shared plumbing makes every timestamp column forget it was UTC.

.NET 02 Dec 2025

CQRS Arrived as a Consequence

Because the write model exposes nothing, the read side could not go through the aggregate - so a second POCO maps the same physical table through a second DbContext. CQRS as an outcome rather than a choice.

.NET 02 Dec 2025

The Model the Scheduler Can Query

The third persistence strategy is the plainest one, and the only one a background poller can interrogate - plus what that poller costs when it has no watermark, no paging and no index.

.NET 01 Dec 2025

When Private Fields Become Column Names

Mapping a fully encapsulated aggregate to relational tables with Property of T of a string - eight tables for one aggregate, eighteen columns, seventeen of them named after private C# fields.

.NET 30 Nov 2025

The Aggregate as One Column

Sales stores four aggregate roots and twenty-five value objects in three tables, by serialising whole aggregates into jsonb - and the reflection resolver that makes reconstitution work bypasses every invariant on the way in.

.NET 30 Nov 2025

The Queries You Cannot Write

What the document strategy really costs - a promoted column, a side table, an in-memory dictionary with a TODO on it, and six update methods that look the row up without its id.

.NET 28 Nov 2025

One Public Member, Sixteen Consequences

Postsale's aggregate has ten private fields and exactly one public member. Reservation, in the same estate, has eighteen. Following that difference all the way down to the database.

.NET 26 Nov 2025

One Domain, Three Dialects

A teaching repo that implements one airline-charter domain three ways on purpose - CRUD, CRUD-plus-rich, and Clean Architecture - and persists it three ways to match. Part 1 of a source-reading series.

Architecture 21 Nov 2025

The Contract That Became Someone Else's Migration

One published type from the Communication module is mapped as an owned entity into TimeManagement's schema - so adding a field to your own contract now needs a migration you do not own.

Architecture 12 Nov 2025

Two Repositories, One Winner

Conferences registers in-memory and EF repositories for the same interfaces and lets last-registration-wins pick - a live lesson in DI as strategy selector, dead registrations as fossils, and a no-op UpdateAsync nobody deleted.

Architecture 11 Nov 2025

The Database Splits Before the App Does

One Postgres database, one schema per module, and entity configurations that are all empty bodies - what ModularMonolith's data layer declares about future service boundaries, and what its migrations quietly gave away.

.NET 17 May 2025

Every Archive Needs an Expiry Date

Retention as a first-class column: how ArchiveKit stamps ExpiresAt at archive time from a TtlDays attribute, hard-deletes expired rows in bounded batches, and runs the whole thing on Lambda with the hosted services switched off. Also, the rows TTL doesn't clean yet. Part 8 of the Archive-on-Delete with ArchiveKit series.

.NET 17 May 2025

Querying the Graveyard

The read side of archive-on-delete: querying archives through promoted typed columns, digging into jsonb payloads for everything else, polling snapshots with a 202 pattern, and an honest accounting of the restore path ArchiveKit doesn't have yet. Part 9 wraps up the Archive-on-Delete with ArchiveKit series.

.NET 16 May 2025

Rebuilding Objects That No Longer Exist

ArchiveKit's snapshot service assembles a full JSON tree of a deleted object graph using nothing but archive rows - the primary data is already gone. Job tickets, a four-state machine, retries with a terminal Failed state, and the single-table assembly limitation I still owe a fix for. Part 7 of the Archive-on-Delete with ArchiveKit series.

.NET 15 May 2025

How to Delete a Family Together

Correlation ids and cascade archiving in ArchiveKit - how one Guid per save turns scattered archive rows into a reconstructable object graph, why cascade happens through the EF change tracker rather than the database, and two honest limits: a naive root heuristic and a CascadeArchive flag the interceptor doesn't read yet. Part 6 of the Archive-on-Delete with ArchiveKit series.

.NET 15 May 2025

One Attribute, a Scanner, and a Registry

How ArchiveKit wires itself up - the [Archivable] attribute's three knobs, an assembly scanner that fails fast at startup instead of quietly at delete time, the static registry behind every lookup, and the AddArchiveKit configuration surface. Plus an honest note about the source generator that doesn't exist yet. Part 5 of the Archive-on-Delete with ArchiveKit series.

.NET 14 May 2025

An Archive Table That Outlives Its Source

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.

.NET 13 May 2025

Fourteen Rows at a Time: Batching Math and the Deletes That Dodge You

Why ArchiveKit's inline archive limit defaults to exactly 14, how EF Core's MaxBatchSize turns archiving into arithmetic, and an honest inventory of every deletion path the interceptor cannot see - synchronous saves, ExecuteDelete, and raw SQL. Part 3 of the Archive-on-Delete with ArchiveKit series.

.NET 13 May 2025

Teaching SaveChanges to Archive Before It Deletes

The anatomy of ArchiveKit's SaveChangesInterceptor - detecting soft-deleted entities in the change tracker, building archive rows with zero extra database reads, and the one line of state-flip ordering that keeps EF from cascade-deleting the archive you just wrote. Part 2 of the Archive-on-Delete with ArchiveKit series.

.NET 12 May 2025

Delete Is Never Just Delete

Hard deletes destroy the audit trail; soft deletes clutter live tables forever. Introducing ArchiveKit, a .NET library that intercepts deletions and stores immutable archive snapshots with TTL policies and cascade archiving.

.NET 11 May 2025

Draining the Archive Without Losing a Row

Archive tables are meant to empty out - a background worker migrates their rows into the current table while live traffic reads and write-through updates race it. This part walks the EF backfill's insert-then-conditional-delete choreography and the timestamp that keeps it honest. Part 9 of the Entity Versioning with VersionKit series.

.NET 10 May 2025

One Query Across Every Version

A point lookup that might hit any of three tables, a list query that should span them all, and writes that must keep a registry honest - this part walks VersionKit's version-aware reader and writer, and the generated UNION view that makes every schema era queryable as if it were current. Part 8 of the Entity Versioning with VersionKit series.

.NET 09 May 2025

Give Old Rows Their Own Table

JSON payloads can migrate lazily because the reader controls the shape - relational rows cannot, because the table is the shape. VersionKit's EF Core answer is table-per-version - archive Orders as Orders_v2 on a schema bump, track every row's home in a registry, and let old rows stay old until something moves them. Part 7 of the Entity Versioning with VersionKit series.