Ode2Code

CSHARP
← Back to csharp
csharp· 8 min read· Mar 12· 21,400 views

Source generators in C# 12: a quiet revolution

Incremental generators changed what library authors can ship without runtime cost. Here's the mental model that finally clicked.

There is a particular satisfaction that comes from understanding a system well enough to predict its failures. Most engineering writing skips the part where you didn't understand it yet — but that's usually the most useful part to read.

What follows is an attempt to write down the things I wish I'd known at the start, in the order that would have helped me. The code samples work; the assumptions are explicit; the conclusions are mine.

The setup

Every project of this kind starts with the same illusion: that the hard part is the algorithm, and once you have the algorithm, the rest is plumbing. The actual ratio, in my experience, runs about 15% algorithm and 85% plumbing, integration, and the strange edge cases that only show up when real users do real things.

ts
1export async function process(input: Input): Promise<Result> {
2 const validated = await validate(input);
3 if (!validated.ok) return { kind: "error", reason: validated.reason };
4
5 const enriched = await enrich(validated.value);
6 const transformed = transform(enriched);
7
8 return persist(transformed);
9}

What changed

The right unit of retry is almost never the thing you started retrying. It's usually two layers down, or one layer up. Finding it is the work.

Once I started attaching cancellation tokens to every layer and propagating them through, an entire category of bug just stopped happening. The other bugs got easier to find. The system started feeling like a system.

Start with observability. Not "we'll add metrics later" observability — actual structured logs with trace IDs, before the first feature ships. The cost of adding it now is half a day. The cost of adding it after the first incident is a week, plus the incident.

HO
Written by

Hana Okafor

.NET Foundation board. Building source generators that make C# feel fun again.

9,850 reputation1 articlesAuthor

Responses (3)

Sort: newest
YV
YV
Yulia Volkov· 2h ago

Spent a year fighting exactly this. The "right unit of retry" framing is the part I wish I'd found three jobs ago.

TR
Tomás Reyes· 4h ago

Strong agree on observability-first. One pushback: structured logging with trace IDs from day 1 is a hard sell on a 2-person team. Curious what the minimum viable shape looks like for you.

DP
Devon Park· 6h ago

The cancellation tokens point is doing a lot of work here. Would love a follow-up on how you actually propagate them through code you don't own.