Every architect hears the voice eventually. It comes at 3 a.m., after the fourth service has re-implemented retry logic slightly differently, after someone ships a service with no health check again, after you open two repos and find two competing conventions for the same config file. The voice is calm and reasonable and it says: “What if we just built our own framework?”
One framework. Our conventions. Everything wired correctly by default. New services in minutes. The voice shows you the vision the way lightning illuminates a laboratory — briefly, gloriously, and leaving out all the details.
I've heard the voice. You've heard the voice. Tonight, in this notebook, we're going to follow it all the way down — past the graveyard where the other frameworks are buried — to the one creature worth stitching together.
Lab Note 01 — The TemptationWhy the voice is so persuasive
The voice isn't stupid. It's reacting to a real disease: cross-cutting drift. In a system of many services, every team keeps re-solving the same undifferentiated problems — configuration, logging, tracing, health checks, retries, message handling, auth plumbing. Each solution is slightly different. Each difference is a future incident, a longer onboarding, a harder audit.
The disease is real. The voice's prescription — a grand unified in-house framework that owns everything — is where the horror story begins.
Lab Note 02 — The GraveyardVisiting the other creatures
Walk behind any large engineering organisation and you'll find it: the graveyard of internal frameworks. CorePlatform.Common, version 2.3.1-final-FINAL. The stones all tell the same story, in four acts:
- The creature demands feeding. A framework is not a deliverable; it's a dependency with a lifecycle. .NET releases a new major version — the framework must upgrade first, and every service waits. A CVE lands in a wrapped library — the framework team is now on the critical path of every deployment in the company.
- The villagers can't read the manual, because there isn't one. Public frameworks survive on documentation, Stack Overflow answers, and ten thousand blog posts. Your in-house creature has a README written eighteen months ago and one person who really understands the message-dispatch internals. That person just got a job offer.
- It eats its creator. The framework team stops shipping product and starts shipping… framework. Roadmaps fill with “migration to v3.” The thing you built to accelerate the business is now a small business of its own, with the org as its only — and captive — customer.
- Nobody new has ever heard of it. Hire a senior engineer and they arrive knowing ASP.NET Core, OpenTelemetry, Polly. They do not arrive knowing
YourCo.Fabric.ServiceBase<T>. Every hire pays a tax that public tooling would have waived.
Note carefully what the graveyard does not say. It doesn't say the disease was imaginary. Cross-cutting drift really was killing them. They just built the wrong creature.
Lab Note 03 — The TwistDon't build a framework. Build a chassis.
Here is the distinction the graveyard died without learning, and it hinges on one question: who calls whom?
A framework calls your code. It owns the lifecycle, the abstractions, the ceiling of what's possible. To leave it, you rewrite.
A chassis is code you call. A thin, boring library of pre-wired defaults sitting on top of proven public tools — plus a service template that starts new services with everything already connected. To leave it, you delete a package reference.
The chassis fixes the disease — every service gets identical config, tracing, health checks, resilience — without the graveyard's four curses, because underneath it is nothing but the public tools every new hire already knows and every CVE scanner already watches.
Lab Note 04 — The AnatomyWhat goes into the creature
The whole chassis should be small enough that one engineer can read it in an afternoon. Its heart is a single extension method:
// Program.cs of every service. This is the whole ceremony.
builder.AddPlatformDefaults("checkout-api");
// ...which is nothing more than honest wiring:
public static WebApplicationBuilder AddPlatformDefaults(
this WebApplicationBuilder b, string service)
{
b.Configuration.AddAzureKeyVaultIfConfigured(); // config, one way
b.AddStructuredLogging(service); // Serilog, JSON, trace IDs
b.AddOpenTelemetryDefaults(service); // traces + metrics, OTLP out
b.Services.AddHealthChecks().AddPlatformProbes(); // /healthz, /ready
b.Services.AddResilienceDefaults(); // Polly: retry, breaker, timeout
b.Services.AddMessagingDefaults(); // MassTransit + outbox pattern
return b;
}
Every line delegates to a tool with its own community, docs and release train. The chassis contributes exactly two things: decisions (one logging shape, one trace header, one health endpoint) and wiring. Longtime readers will spot an old friend in there — the messaging default bakes in the outbox pattern, so no team ever re-invents dual-write bugs again. And because the tracing default stamps every log with a trace ID, the detective gets her thread for free in every service, from day one.
Alongside the library, a service template (dotnet new our-service) that emits a runnable service with the chassis referenced, a Dockerfile, CI pipeline, and a folder structure. Templates are even safer than libraries: they're a starting point, not a dependency. Nothing to upgrade, nothing to escape.
Lab Note 05 — Keeping It TameThe laws of the laboratory
- Thin, forever. The chassis wraps; it never re-abstracts. The moment someone proposes
IOurMessageBus“so we can swap MassTransit later,” read them Lab Note 02 aloud. Leaky custom abstractions are how creatures start growing extra arms. - Deletable by design. Any service must be able to drop the chassis and hand-wire the same public tools in a day. If leaving is expensive, you've built a framework and simply named it politely.
- Versioned like a product. SemVer, a changelog humans can read, and no breaking change without a migration note. The chassis team's customer is every other team; act like it.
- Paved road, not a prison. The chassis is the easy, blessed path — but a team with a genuine exotic need can step off it without asking permission. Roads get walked; walls get climbed.
- Steal, don't stitch. Before writing anything, spend a day confirming the ecosystem hasn't already solved it. It almost always has. Your differentiation is the selection and wiring, not the plumbing.
Lab Note 06 — The ExceptionWhen you really do build the monster
Honesty compels a footnote: some organisations genuinely outgrow the public ecosystem — when your scale, latency floor, or regulatory surface is measurably beyond what shared tooling serves, and you can fund a permanent team whose entire product is the platform. Netflix built theirs. So did a handful of banks. They didn't do it to standardise config files; they did it because they hit walls you can name with numbers.
The test is brutal and simple: if the framework wouldn't survive as a product with a funded team and a roadmap, it doesn't deserve to exist as a side project with neither.
Closing note in the lab book
The voice at 3 a.m. was right about the disease and wrong about the cure. You don't need a grand creature stitched from custom abstractions — you need a small, boring, deletable one: a chassis of decisions and wiring standing on the shoulders of tools the whole industry keeps alive for you.
Build that, and new services start consistent in minutes, incidents stop being archaeology, and no villager ever comes for you with a torch. The mad scientists who thrive aren't the ones who built the biggest monster.
They're the ones who knew exactly how little to sew. ⚡