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
  • 136 matching
Architecture 16 Jan 2026

Compensation That Cannot Fire

Inflow's one real saga has four compensation methods and no message that can ever trigger them. Its state lives in memory, its ordering rests on an undocumented property of a background service, and its failure mode is a denied bonus recorded as success.

Architecture 15 Jan 2026

A Saga Held Together by a String

Inflow's withdrawal flow is a three-module round trip with a compensating branch and no saga class. The correlation between the halves is a magic string declared three times and a JSON blob written by hand on one side and deserialised on the other.

Architecture 15 Jan 2026

Lock the Customer, Half the Estate Notices

Locking a customer flips a flag in three of the four modules that hold one. Wallets has Lock and Unlock methods on its Owner entity and nothing in the estate ever calls them - so the module that moves money is the module that never hears.

Architecture 14 Jan 2026

One Guid, Five Customers

A single Guid minted at sign-up becomes a user, a customer, a payments customer, a wallet owner and a saga id - four Postgres schemas, five field names, zero foreign keys and nothing that declares the equality.

Architecture 13 Jan 2026

Onion Versus Folder

Wallets is four projects, Payments is one, and the same author wrote both in the same week. Three claims are usually made for the extra assemblies - one is true and verifiable in XML, one is weaker than it looks, and one is provably false.

Architecture 13 Jan 2026

The Read Side the Layers Lost

Wallets abstracts its queries behind a storage interface that returns aggregates and maps in memory. Payments injects the DbContext and projects in SQL. On the read path the layered module is the slower and more coupled one.

Architecture 12 Jan 2026

Money Without a Currency

Inflow models money as an Amount that wraps a bare decimal and a Currency that lives beside it on the entity. The two never travel together, nothing rounds, and the column is unconstrained numeric.

Architecture 11 Jan 2026

The Version That Counts to Two

Inflow's aggregate root increments its Version at most once per instance lifetime. As a concurrency token that is correct; as a version number it is a lie - and the one unit test that touches it documents the latch instead of catching it.

Architecture 10 Jan 2026

A Setter on the Ledger

Inflow's Wallet guards its transfers behind a private HashSet and then exposes a public setter for it. Assigning an empty list zeroes any balance with no exception, no version bump and no trace - and Entity Framework never needed the setter.

Architecture 10 Jan 2026

The Reference That Points at Itself

Each half of an Inflow transfer stores a referenceId in its metadata. On both legs that reference is the leg's own id - so the two halves of a transfer cannot be joined from the data they persist.

Architecture 09 Jan 2026

Two Aggregates, One Method

Wallet.TransferFunds mutates a second aggregate root inside the first one's method - the textbook DDD violation, committed for a good reason. The reason survives the domain layer and does not survive the handler.

Architecture 08 Jan 2026

A Million Is Where the Wallet Breaks

Inflow's Amount value object rejects anything above one million, and the wallet balance is an Amount. Two legal credits of six hundred thousand leave a wallet that can still take money in and can never be read or spent again.

Architecture 08 Jan 2026

The Wallet That Adds Itself Up

Inflow's Wallet has no balance column - the balance is a fold over the transfer ledger, computed the same way on the write side and the read side. It is the best decision in the module, and it costs more than it looks.

Architecture 07 Jan 2026

Four Architectures in One Solution

Inflow is a modular monolith whose modules agree on their boundaries and disagree about everything inside them - a four-project onion next to a single feature-sliced assembly. Part 1 of a series reading the money-moving half of the estate.

Architecture 06 Jan 2026

Ten Hours and No Way Back

The rewrite multiplied the JWT lifetime by ten and deleted the only way to revoke a token early - one change in a JSON file, the other an absent folder, and neither visible in any diff of the domain.

Architecture 06 Jan 2026

The Rewrite Kept Every Bug

Four non-trivial defects appear at near-identical line numbers in both builds of the same product - a ground-up rewrite by the same authors relocated them rather than finding any.

Architecture 05 Jan 2026

In-Process Is Not Synchronous

Trill's monolith routes every cross-module event through an unbounded channel drained by one background service - so its flagship end-to-end test has to sleep for two seconds to observe the architecture working.

Architecture 04 Jan 2026

Eighteen Containers Become Two

Running Trill as microservices takes eighteen containers and twenty-two published ports; running the same product as a monolith takes mongo, redis and dotnet run - and only the monolith still starts from a clean clone.

Architecture 04 Jan 2026

Minimal APIs, Written by Hand

Trill's monolith implements typed Get, Post, Put and Delete extensions over IEndpointRouteBuilder on .NET 5 - the framework .NET shipped eighteen months later, complete with query binding by string replacement.

Architecture 03 Jan 2026

Every In-Process Call Pays for MessagePack

Two lines in Trill's module client serialise and immediately deserialise every cross-module message, buying a future network hop at the cost of a round trip that never leaves the heap - and there is a benchmark project defending the choice.

Architecture 02 Jan 2026

Guid.Empty Is a Mode Flag

Trill's monolith puts the envelope fields on the message itself, then uses one sentinel value to mean this-is-a-synchronous-call in three unrelated subsystems that never mention each other.

Architecture 02 Jan 2026

The Contract Checker They Built After the Drift

The Trill monolith ships a startup-time validator that compares independently declared copies of the same message and crashes the app on a mismatch - the most original idea in either build, adopted by four declarations out of twenty-two.

Architecture 01 Jan 2026

AddX, UseX, and Two Deliberate Violations

Trill's hand-rolled framework follows the ASP.NET Core registration convention with unusual discipline, then breaks it twice on purpose - and the exceptions turn out to be more instructive than the rule.

Architecture 31 Dec 2025

A Framework Instead of Twenty-Four Packages

Trill's saga microservice references twenty-four third-party packages; the same saga as a module references one - because the monolith deleted Convey and rewrote 4,600 lines of it by hand.

Architecture 31 Dec 2025

One Database, Eleven String Literals

Four physical Mongo databases collapse into one when Trill is rebuilt as a monolith - and the only thing keeping the modules apart afterwards is a private const string copied into eleven files.