Skip to content
kc@kumarChandrachooda.com:~$ cd /blog/series/trill-two-ways && read --section="top" 0%
Series

Trill Two Ways

In reading order.

  • 13 parts
  • ≈ 88 min total
  • 13 published
Part 1 29 Dec 2025 7 min read

The Same App, Built Twice

DevMentors shipped Trill as nine microservice repos, then rebuilt the identical product as a modular monolith three months later - giving us a controlled experiment in architecture that almost never exists in public.

Part 2 30 Dec 2025 6 min read

Boundaries the Compiler Enforces

Trill's monolith makes every module type internal and gives each one an explicit friend list, so a cross-module reach is not a code-review conversation - it is a build error.

Part 3 31 Dec 2025 6 min read

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.

Part 4 31 Dec 2025 6 min read

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.

Part 5 01 Jan 2026 6 min read

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.

Part 6 02 Jan 2026 6 min read

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.

Part 7 02 Jan 2026 7 min read

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.

Part 8 03 Jan 2026 7 min read

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.

Part 9 04 Jan 2026 7 min read

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.

Part 10 04 Jan 2026 7 min read

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.

Part 11 05 Jan 2026 7 min read

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.

Part 12 06 Jan 2026 7 min read

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.

Part 13 06 Jan 2026 9 min read

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.