Your source of geek knowledge

Y

Latest stories

Azure Service Bus: One topic, many subscriptions

A

TL;DR: A single Azure Service Bus topic can be a reasonable starting point for one-to-many messaging. The topic receives published messages, and subscriptions provide separate delivery views for consumers. As the number of subscriptions, filters, and messages grows, the shared topic can become a place where routing work and storage pressure meet. Splitting event streams across topics may help, but adding entities alone does not accelerate a system. This post is part of a short series on Azure...

Azure Service Bus: Count your filters

A

TL;DR: Azure Service Bus can publish one message to a topic and deliver it to multiple consumers. A topic is the shared destination, a subscription is a consumer-specific view, and a filter decides whether a message is copied to that subscription. In high-throughput systems, the number of subscription rules can matter more than the filter type itself. This is the first post in a short series on Azure Service Bus topology under load. The series looks at filter count, subscription fan-out (one...

Keep the gains: performance regression testing without fooling yourself

K

TL;DR: Keep only the benchmarks that protect important hot paths. Use baseline/diff comparisons to catch regressions, but do not trust noisy shared runners blindly. Performance regression testing needs stable machines, clear thresholds, and restraint. After a successful performance investigation, the benchmark folder looks valuable. It contains the history of the work: experiments, false starts, before-and-after comparisons, warmup cases, exception cases, and small probes that helped explain...

The scheduler is part of your message pump

T

TL;DR: The async model is a contract. In .NET, async methods are expected to do little CPU work, spend most of their time awaiting input/output, and make long-running CPU work explicit. Lease renewal depends on that contract. If a handler hides blocking or CPU-heavy work inside an async method, the scheduler assumptions behind renewal can fall apart. The message pump depends on the broker API, but it also depends on the runtime’s execution model. After publishing the previous article...

When the handler outlives the lease

W

TL;DR: A visibility timeout is a lease. It tries to keep two consumers from working on the same queue message at the same time, but only for a limited period. If message handling takes longer than that period, the pump must renew the lease while business code continues to run. That sounds like a small addition until renewal needs scheduling, cancellation, shutdown behavior, mutable pop receipts, delete coordination, and a policy for what to do when renewal fails. The first version of the...

Event Sourcing: Aggregates, Dynamic Consistency Boundaries, or what?

E

In part eleven of this series on event sourcing, we make a small detour to discuss consistency boundaries. I never thought much about this aspect until recently, when I watched a couple of conference talks that all made a big fuss about domain-driven design’s aggregates, and had a discussion with Sara Pellegrini about dynamic consistency boundaries. This post is less about the resulting solution we have and more about the reasoning that led to it (and that might lead to another solution...

A benchmark win is not the finish line

A
Profile again: The benchmark is not the finish line

TL;DR: Once a benchmark shows a win, put the optimized code back into the profiling harness. Compare the before and after memory and CPU profiles to see whether the larger execution path benefits too. A good benchmark table feels great. The before number is slower, the after number is faster, allocations drop, and the ratio looks impressive. After hours of staring at profiler stacks and benchmark output, that table feels like the finish line. Unfortunately, the table only describes the isolated...

Message pumps fail in the transaction details

M

TL;DR: Reading bytes from a queue is the easy part of a message pump. Things get difficult when message handling writes to a database, sends more messages, fails halfway through, moves to another broker, or runs in a cloud service with different transaction semantics. A small infrastructure project can quietly turn into a platform commitment. None of this looked particularly scary when we started. It looked like a loop: read from a queue, deserialize a message, find the handler, and call it. We...

Recent Posts