C# and .NET
Where the framework stops and the runtime starts. Request pipelines, async continuations, DI lifetimes, EF Core concurrency, and the API decisions that get expensive to reverse.
Sessions I have run for product teams. The rooms were closed; the conclusions were not worth keeping to myself.
Every session here was built for one team with one problem, and none of them were open sign-ups. What is published below is the part that survives the team: the failure modes, the trade-offs, and the code. Where a company or a client name would identify them, the entry says so instead of hiding the gap.
Most of these started as a question one engineer could not get answered by reading documentation — usually because the documentation described the mechanism and not the consequence. That gap is the reason the sessions exist.
I take sessions on C#, Java, .NET, SQL, system design, and distributed systems, and adapt the material to what the team already knows so nobody spends an afternoon being taught things they use every day.
Most requests arrive as a specific stuck point rather than a topic. These are the areas I can run a session on, adapted to what the team already knows.
Where the framework stops and the runtime starts. Request pipelines, async continuations, DI lifetimes, EF Core concurrency, and the API decisions that get expensive to reverse.
Service boundaries that survive a second squad, transaction boundaries that do not span a network call, and a testing strategy that survives the refactor.
Schema design, indexing, isolation levels, and migrations against a live table. Where correctness and throughput turn out to be the same decision.
Reviews of real designs rather than textbook ones. Constraints, the options that were rejected, and the failure mode that decides the shape of the system.
Idempotency, retries, partial failure, and what actually happens when a dependency is late. Taken from systems that ran in production, not from diagrams.
Broker selection, partition strategy, consumer rebalancing, replay, and schema evolution. Usually the session that shows a team holding two incompatible answers.
Azure and GCP platforms, containers, Kubernetes, Terraform, and a CI pipeline that produces the same artefact every time instead of most times.
Threat modelling for integrations that move money: idempotent retries, webhook verification, secret handling, and an audit trail worth having afterwards.
A team could publish but could not reason about what happened after a consumer crashed mid-batch. We rebuilt the failure story around idempotency keys, a poison-message path, and replay that operators had actually rehearsed.
Four brokers, no capacity plan, and a broker upgrade that ate a weekend. The session covered what changes when the platform runs the cluster anyway: compatibility gaps, partition mapping, dual running, cutover, and the rollback nobody had tested.
Two systems that had to agree, maintained by hand, forever. We replaced the nightly job with logical replication into a stream, then spent most of the session on the part that is actually hard: schema evolution and what a consumer does when it receives a shape it has never seen.
Built for a team whose services passed load tests and still timed out in production. We read a state machine out loud, traced a continuation onto a thread pool, and found where a request was blocking something that looked asynchronous.
Middleware order is not a matter of taste, and a team was paying for it. Starting at Kestrel and ending at the endpoint, this mapped every hop a request makes, then showed which orderings silently disable features you are still paying to license.
A contract had shipped that could never change without breaking clients. We rewrote it around an honest error model, pagination that does not lie, and an OpenAPI document treated as a build artefact rather than documentation written afterwards.
Two users editing one record, last write winning, no signal to either. The session covered isolation levels as they actually behave on the target database, when optimistic concurrency is the right answer, when it is not, and why retry loops turn a race condition into a deadlock.
A third-party callback was the only part of the flow nobody owned. We drew the trust boundaries, moved the secret handling, made the audit trail answerable, and scoped what genuinely had to live inside the cardholder data environment.
Most sessions above began as a single engineer's question that turned out to be a design problem. If that is what you are looking at, bring the constraint and the failure, not a proposed solution — the solution is the easy half.