Shared Code, Shared Problems

7 parts, in reading order.

Jun 15, 2021·6 min read

Shared Code, Shared Problems, Part 1: Shared Code as Packages, Not Copied Source

Copying a helper into every service is the fastest way to share code on day one and the slowest by day ninety. We moved messaging, authentication and HTTP clients into versioned packages. The post covers what that bought us, and the drift it introduced.

dotnetnugetarchitecturemicroservices
Oct 11, 2022·6 min read

Shared Code, Shared Problems, Part 2: One Pipeline for Twenty-Five Services

When about twenty-five services build, version and deploy the same way, a fix to one step is a fix for all of them. What we standardised, how versions get allocated, and the lockstep that caught people out.

dotnetjavaci-cddevops
Dec 13, 2022·6 min read

Shared Code, Shared Problems, Part 3: The HttpClient Race

A shared HTTP client is shared mutable state, and the first place that shows is in how it's created. What goes wrong when two callers build a client at the same moment, and how to make creation safe and testable.

dotnethttpclientconcurrencytesting
Jan 17, 2023·6 min read

Shared Code, Shared Problems, Part 4: Fix Once, Break Everywhere

After a framework upgrade, an in-memory cache in shared code stopped clearing when reference data changed. How it showed up, why the fix belonged in the shared library, why it's easy to confuse with a separate move to a shared cache, and the test we didn't have.

dotnetcachingtestingarchitecture
Feb 14, 2023·6 min read

Shared Code, Shared Problems, Part 5: Check the Status Before You Trust the Payload

A failure that deserialises into an empty success is worse than a crash. A shared HTTP client turned rejected requests into confident-looking results, which showed up as two different symptoms. Fixing it in one place fixed every caller.

dotnethttperror-handlingapi-design
Mar 14, 2023·6 min read

Shared Code, Shared Problems, Part 6: The 403 That Kept Coming Back

Users were told they were forbidden from things they were allowed to do, but only sometimes. The fixes that treated the symptom didn't last. The cause was a per-request header sitting in a shared client's default headers. How we found it, and the test that pins it.

dotnethttpclientauthorisationdebugging
Jun 13, 2023·7 min read

Shared Code, Shared Problems, Part 7: Your Background Service Doesn't Have a Request

'Cannot access a disposed object' in a message handler usually means a scoped service lives in something that outlives its scope. Hosted services have no request scope. A per-message scope fixes it, and the fix belongs in the shared library.

dotnetdependency-injectionef-corebackground-services