Why I’m Writing This
In one of my recent projects, we had a fairly common requirement on paper:
“Send notifications when something happens.”
But as usual, the reality was more complex:
- Notifications had to be real-time
- System needed to scale
- Multiple consumers (email, UI, future integrations)
- And most importantly — no tight coupling
I’ve seen systems break because notifications were treated as a “side feature”. So I thought I’d share how I approached designing this properly.
The Problem with the “Simple” Approach
The first instinct is usually something like:
API → Save to DB → Send Email / Notification
Looks fine initially. But over time:
Every feature starts calling notification logic directly
Adding a new channel (SMS, push) becomes painful
Failures in notification start impacting core business flow
I’ve been there — it doesn’t scale well.
How I Think About It
I try to separate concerns clearly:
- Business action happens (Order placed, Payment done)
- System emits an event
- Other parts of the system react to it
That naturally leads to an event-driven approach.
The Architecture I Use
At a high level:
Each component has a very specific responsibility.
Where MediatR Fits
Inside the API, I use MediatR mainly for decoupling.
Instead of controllers directly calling services:
- Controller sends a command
- Handler processes it
- Business logic stays clean and testable
It also gives me a clean place to hook in things like logging, validation, etc.
Why Azure Service Bus
Once the business action is completed (say, order created), I don’t send notifications directly.
I publish an event.
That’s where Azure Service Bus comes in:
- Decouples producer and consumer
- Handles retries, failures
- Lets multiple consumers subscribe
Today it might be just email + UI. Tomorrow it could be analytics, audit, external systems.
I don’t want to rewrite my core logic for that.
SignalR for Real-Time
For user-facing updates, polling is not a great experience.
That’s where SignalR helps:
- Server pushes updates instantly
- Works well for dashboards, alerts, chat-like scenarios
In our case, once the notification service processes an event, it pushes updates to connected clients.
End-to-End Flow (How It Actually Runs)
- User places an order
- API receives request
- MediatR handler processes and saves it
- Event gets published to Service Bus
- Notification service picks it up
- Sends email + pushes real-time update via SignalR
The important part:
👉 Order creation does not depend on notification success
Trade-offs (Because Nothing Is Free)
This approach is not “simple”:
- More moving parts
- Requires monitoring (Service Bus, consumers)
- Slight delay (eventual consistency)
But in return, you get:
- Scalability
- Flexibility
- Cleaner architecture
For me, that trade-off is worth it in most real systems.
Where This Works Really Well
I’ve seen this pattern work nicely in:
- E-commerce systems
- Banking alerts
- Monitoring dashboards
- Any system with user-triggered events + multiple consumers Final Thoughts
One thing I’ve learned over time:
Notifications should be treated as a separate system, not a side-effect.
Using MediatR, Service Bus, and SignalR together helped me keep things:
- Decoupled
- Scalable
- Easier to evolve
If you’ve built something similar or approached it differently, I’d be interested to hear your thoughts. Always good to compare patterns and learn.

Top comments (0)