Services in Practice

10 parts, in reading order.

Jul 13, 2021·5 min read

Services in Practice, Part 1: Two Kinds of Call, REST or Events?

Every call between services is either asking for something or announcing something. Mixing the two up is how systems end up slow, fragile and hard to change. The test I use, with a booking example, and what each choice couples you to.

dotnetmicroserviceskafkaarchitecture
Aug 17, 2021·6 min read

Services in Practice, Part 2: Who Owns This Data? No Shared Tables

If two services read the same table, they aren't two services. They're one service with a network between its halves. The ownership rule I use, the two honest ways to get data you don't own, and the reporting problem that always follows.

dotnetmicroservicesdataarchitecture
Oct 12, 2021·6 min read

Services in Practice, Part 3: Circuit Breakers for Calls Between Services

The asynchronous side of a system can be made to survive almost anything. The synchronous side is where an outage in one service spreads to every service that calls it. A slow dependency ties up threads. The timeout, retry and breaker settings I'd put in front of every downstream call stop that.

dotnetpollyresiliencemicroservices
Dec 14, 2021·6 min read

Services in Practice, Part 4: Your Readiness Probe Is Lying

An open port isn't a healthy service. A container whose database connection has expired can pass a TCP probe all day while it fails every real request. What readiness and liveness should each check, and how to avoid taking every instance out of rotation at once.

dotnetkuberneteshealth-checksoperations
Feb 15, 2022·6 min read

Services in Practice, Part 5: Bridging Kafka and RabbitMQ for Systems You Don't Own

Your own services speak one messaging language. The system you need to talk to speaks another, and you can't ask it to change. Meet it where it is, keep the translation in one place, and keep the bridge honest about its own health.

dotnetkafkarabbitmqintegration
Mar 15, 2022·6 min read

Services in Practice, Part 6: Correlation IDs Across Systems You Can't See Into

When a message crosses into someone else's system, its ID is the only thread you can pull. Where to set a correlation ID, how to carry it through events and HTTP calls, what to log, and how it shortens an investigation that spans two teams.

dotnetobservabilityloggingintegration
Aug 16, 2022·6 min read

Services in Practice, Part 7: Partition Zero, the Assumption That Blocks Scaling

Code that only works with one partition quietly decides you'll never scale out. It can run for years without a problem, right up to the day you add a second consumer. The pattern to look for, why it hides, and what to do instead.

dotnetkafkascalingreliability
Apr 18, 2023·6 min read

Services in Practice, Part 8: Orchestration or Choreography? Merging Duplicate Records

Merging two customer accounts touches orders, payments and addresses, each owned by a different service. A distributed transaction isn't the answer. How to decide between one service that owns the flow and events that carry it, and why this one needed an owner.

dotnetmicroservicessagaarchitecture
May 16, 2023·6 min read

Services in Practice, Part 9: A Saga Where Every Participant Answers

A participant that fails silently leaves the whole saga waiting. The rule that keeps a multi-service merge honest is simple: always reply, even if the reply is 'I failed'. The participant's side of the account merge, and what compensation you still need.

dotnetsagamicroservicesreliability
Jul 18, 2023·6 min read

Services in Practice, Part 10: The Helper That Made a Query per Item

An N+1 hides best inside a helper that looks cheap. A category page asked for translated product names one item at a time, and each call was a round trip. The fix is a batched query and a cache keyed by what callers actually ask for, with a weak spot in invalidating it.

dotnetperformancecachingredis