Skip to content
Katabench
Try free

Katabench blog

Engineering field notes

Practical, production-minded guides for .NET engineers. Learn the mechanism, see the failure mode, and leave with an instinct you can use in real code.

Latest articles

RSS feed →
Architecture & Design 7 min read

Aspire Service Discovery: Names, Ports, Replicas

Learn how Aspire service discovery turns logical names into endpoints with WithReference, HttpClient resolution, health checks, and replica load balancing.

Read article →
Architecture & Design 9 min read

Circuit Breaker Pattern in .NET with Polly

Build a circuit breaker in modern .NET with Polly and HttpClient resilience. Tune the failure window, compose retries safely, and prove recovery.

Read article →
Architecture & Design 8 min read

Message Queue vs Event Bus: Choose the Topology

Compare message queues, event buses, and pub/sub by delivery topology. Choose competing workers or fan-out, then design retries and ordering honestly.

Read article →
Testing & Refactoring 8 min read

Mutation Testing in C# with Stryker.NET

Mutation testing in C# plants controlled bugs and asks whether your tests notice. Learn Stryker.NET, triage survivors, and set useful CI gates.

Read article →
Security & Reliability 8 min read

Path Traversal Vulnerability in ASP.NET Core

A path traversal vulnerability lets user input escape a trusted directory. See the unsafe C# patterns, the containment check, and tests that prove it.

Read article →
.NET Performance 8 min read

C# String Concatenation Performance, Measured

Choose between +, interpolation, StringBuilder, and direct writes in modern C#. Fix repeated copying, then verify the result with allocation benchmarks.

Read article →
Architecture & Design 7 min read

Structured Logging in .NET: Write Logs You Can Query

Learn structured logging in .NET with ILogger message templates, named fields, scopes, correlation IDs, safe data handling, and query-first design.

Read article →
.NET Performance 7 min read

CancellationToken in ASP.NET Core: stop doing work nobody wants

A disconnected client does not make your database query disappear. Learn how RequestAborted flows through ASP.NET Core, EF Core, and HttpClient, where cancellation should stop, and how to test it.

Read article →
Architecture & Design 7 min read

Transactional outbox pattern in .NET: publish without losing messages

Saving data and publishing an event are two writes that can disagree. Build a transactional outbox with EF Core, a retrying publisher, and idempotent consumers so crashes do not lose business events.

Read article →
Databases & EF Core 7 min read

Optimistic concurrency in EF Core: stop silent overwrites

Two users edit the same row and the last save silently wins. Use EF Core concurrency tokens, inspect the generated UPDATE, handle DbUpdateConcurrencyException, and test the race with two DbContexts.

Read article →
Architecture & Design 8 min read

AddSingleton vs AddScoped vs AddTransient: what each promises

AddSingleton vs AddScoped vs AddTransient in plain terms: what each lifetime promises, sensible defaults, and the captive dependency bug that ships.

Read article →
.NET Performance 8 min read

C# async await mistakes that pass code review

The C# async await mistakes that pass code review: async void, fire and forget tasks, missing CancellationToken plumbing, and blocking on .Result.

Read article →
Architecture & Design 8 min read

Caching strategies: cache-aside, invalidation, and stampedes

Caching strategies from the cache-aside flow to the hard parts: invalidation owned by a human and stampedes tamed by single-flight and jitter.

Read article →
Testing & Refactoring 8 min read

Code smells: a working catalog of six, with C# examples

Code smells are symptoms, not verdicts. Six worth knowing, with C# examples: the tell for each, why it hurts, and the refactoring move that clears it.

Read article →
Databases & EF Core 7 min read

Connection pooling: why your app ran out of connections

Connection pooling explained from the failure end: what a connection costs, the three ways pools drain, and why the timeout blames the wrong request.

Read article →
Testing & Refactoring 9 min read

Cyclomatic complexity: what the number actually tells you

Cyclomatic complexity counts the independent paths through a method. How to compute it by eye, what a score of 10 predicts, and how to reduce it for real.

Read article →
.NET Performance 8 min read

.NET garbage collection explained: what gen 0, 1, and 2 cost

.NET garbage collection explained: why most objects die young, what gen 0, 1, and 2 collections cost, and why the large object heap hurts latency.

Read article →
Databases & EF Core 8 min read

How do database indexes work? B-trees, page by page

How do database indexes work? A B-tree is a small sorted structure with huge fanout, so a lookup reads a handful of pages instead of the whole table.

Read article →
Security & Reliability 8 min read

Idempotency in API design: surviving the retry you didn't send

Every serious client retries. How the idempotency key pattern and a database unique constraint keep a retried payment from becoming two charges.

Read article →
Security & Reliability 8 min read

Rate limiting algorithms: how token buckets forgive bursts

Rate limiting algorithms compared: why fixed windows leak double the limit, how token buckets forgive bursts, and what a good 429 response returns.

Read article →
Testing & Refactoring 8 min read

Unit testing best practices: test behavior, not implementation

Unit testing best practices that survive refactoring: AAA structure, behavior-first assertions, a healthy test pyramid, and determinism over flakiness.

Read article →
Testing & Refactoring 7 min read

Primitive obsession: the bug the compiler was begging to catch

When everything is a string, a decimal, or a Guid, the type system can't tell your arguments apart. Value objects in modern C#, the bugs they delete, and when they're overkill.

Read article →
.NET Performance 9 min read

Sync over Async: Diagnose .NET Thread Pool Starvation

Learn how sync over async causes .NET Thread Pool starvation, spot it with dotnet-counters, capture blocking stacks, and fix ASP.NET Core latency.

Read article →
Databases & EF Core 7 min read

Skip and Take will betray you: offset vs keyset pagination

OFFSET pagination reads every row it skips, so page 2,000 costs 2,000 pages of work. Keyset pagination seeks straight to the next page. The SQL, the EF Core, the trade-offs.

Read article →
.NET Performance 7 min read

The LINQ query that ran twice: multiple enumeration and other deferred-execution traps

An IEnumerable isn't a list; it's a promise to do work later. Enumerate it twice and the work happens twice, including, with EF Core, the database query.

Read article →
Security & Reliability 7 min read

ReDoS: the innocent regex that can take down your API

Catastrophic backtracking turns an email regex into a denial of service: 30 characters, nearly a minute of CPU. Why nested quantifiers explode and how .NET lets you defuse them.

Read article →
Engineering Practice 7 min read

Tutorial hell: why you can finish every course and still freeze at a blank file

Watching code get written trains recognition, not recall. Why tutorials feel like progress, why the skill doesn't transfer, and how to build a loop that does.

Read article →
Engineering Practice 6 min read

Coding interviews are broken, but the skills they fumble are real

Whiteboard interviews measure the wrong slice of engineering. The case for practicing what predicts a good engineer: correct, fast, well-structured, secure code.

Read article →
Security & Reliability 8 min read

The OWASP Top 10 through a C# lens

A practical tour of the OWASP Top 10 for .NET developers: the ASP.NET Core and EF Core patterns behind broken access control, injection, SSRF, and overposting.

Read article →
Security & Reliability 6 min read

SQL injection is still alive, and it's hiding in your C#

SQL injection is supposedly solved, yet it's still in the OWASP Top 10. The C# patterns that keep it alive in EF Core and ADO.NET, and how to kill them.

Read article →
Architecture & Design 6 min read

Architecture fitness functions: tests that fail the build when your layers rot

Architecture decays because nothing fails the build when the domain references the DbContext. Fitness functions with ArchUnitNET assert layering and dependency rules in CI like any test.

Read article →
Architecture & Design 6 min read

Hexagonal architecture in .NET without the dogma

Ports and adapters explained in plain C#: domain in the center, ports as interfaces, adapters as infrastructure. Why it beats layered spaghetti, and when it is overkill for a CRUD app.

Read article →
Architecture & Design 6 min read

Dependency inversion in C# is not about your DI container

The D in SOLID is the most quoted and least applied principle. Dependency inversion means depending on abstractions you own and pointing dependencies inward, not registering services.

Read article →
Testing & Refactoring 5 min read

A test-first playbook for refactoring legacy C# safely

How to refactor legacy C# without breaking it: write characterization tests first, then take small behavior-preserving steps (extract method, introduce a seam, replace conditional with polymorphism).

Read article →
Engineering Practice 7 min read

Green checkmarks are incomplete: grading C# beyond correctness

A green check can prove output without proving the solution scales. Learn how performance, allocation, query, and structure gates turn a result into actionable feedback.

Read article →
Testing & Refactoring 6 min read

Clean code is a vibe until you measure it

Four code quality metrics you can actually automate in C#: cyclomatic complexity, nesting depth, method length, and duplication, with reasonable thresholds and a refactor that passes them.

Read article →
Databases & EF Core 7 min read

EF Core habits that quietly wreck performance

Nine EF Core habits that pass every test and quietly tank performance in production: missing AsNoTracking, fetching whole entities, N+1, cartesian explosion, counting in memory, and more.

Read article →
Databases & EF Core 6 min read

Your LINQ is fast; your query plan isn't

A perfectly written EF Core query can still do a sequential scan: no index, or a function on a column makes it non-sargable. How to read a query plan and fix it.

Read article →
Databases & EF Core 6 min read

IQueryable vs IEnumerable: the one return type that decides where your query runs

Returning IEnumerable, or calling ToList too early, moves filtering and paging into C# memory. How one type change turns an indexed WHERE into loading a million rows.

Read article →
Databases & EF Core 6 min read

The N+1 query problem in EF Core: the most expensive habit in .NET

An EF Core loop that looks innocent fires one query per row. It passes every unit test and dies in production. How N+1 happens, the SQL it generates, and the fix.

Read article →
Engineering Practice 5 min read

Deliberate practice for programmers: why a green check isn't feedback

Repetition doesn't make you better; deliberate practice does. It needs immediate, specific feedback at the edge of your ability, and most coding practice fails that test badly.

Read article →
Engineering Practice 6 min read

How senior .NET engineers actually keep their edge

It isn't grinding more LeetCode for correctness. Seniors practice the things production grades: performance, data-access shape, design, and security. Here's the difference.

Read article →
.NET Performance 6 min read

The premature optimization myth: what Knuth actually said

The most-abused quote in software lets developers dodge thinking about performance entirely. Here's Knuth's real argument, and why finding the 3% requires an instinct you have to train.

Read article →
.NET Performance 5 min read

Span<T>, Memory<T>, and stackalloc: when zero-allocation C# is worth it

Span<T> and stackalloc let you parse and slice without allocating, but they have real limits. Here's when zero-allocation C# earns its keep and when it's overkill.

Read article →
.NET Performance 6 min read

The allocation tax: why correct, O(n) C# can still be slow

In .NET, correct and algorithmically optimal code can still drag, because every needless allocation feeds the GC. Here's how to spot and cut allocation pressure in C#.

Read article →
.NET Performance 6 min read

Big-O isn't interview trivia: where complexity actually bites in production

Big-O gets crammed for interviews and forgotten. But quadratic C# passes your tests and melts in prod. Here's where it bites and how to make complexity an instinct.

Read article →

Get new puzzles and .NET tips in your inbox

A short note when fresh kata land, plus the C# and performance tricks behind the grading. No spam, unsubscribe anytime.