Is Redis Overkill? Rethink SignalR Backplane with PostgreSQL



This content originally appeared on Level Up Coding – Medium and was authored by Stefano Giannattasio

Redis isn’t always the right fit. Here’s how PostgreSQL can serve as a pub/sub backplane for SignalR in distributed, low-throughput applications.

Photo by Tarek K on Unsplash

SignalR is a powerful framework for adding real-time capabilities to .NET applications. Whether you’re building chat apps, collaborative dashboards, or live feeds, SignalR makes it seamless to push data from server to client. However, things get tricky when you scale out your application.

In a typical single-node setup, SignalR connections (usually WebSockets) are handled by one server. Messages from the server to connected clients go directly through that server’s memory. But once you scale your application across multiple instances — for example, in a Kubernetes cluster or load-balanced environment — each instance has its own set of connections. A message sent to a user connected to another instance is simply lost unless the servers can talk to each other.

This is where a backplane comes in.

What is a Backplane?

A backplane is a shared messaging infrastructure that allows different SignalR server instances to communicate. When one server wants to send a message to a client that’s connected to another server, it sends the message to the backplane, which then distributes it to all instances. Each instance checks whether the message is for one of its clients.

Out of the box, SignalR supports Redis as a backplane, and it works well for most high-throughput production scenarios. Redis provides a publish/subscribe model that scales reliably and is well-tested.

But what if you’re running a lower-throughput application? Is Redis overkill?

PostgreSQL as a Lightweight Backplane

Sometimes, you might choose to use SignalR in your .NET app to push occasional messages to the client — not for high-frequency scenarios like live chats or real-time games, but for things like push notifications or simply letting the client know that something has changed. These are typically low-throughput use cases.

That said, just because SignalR traffic is minimal doesn’t mean the overall application won’t need to scale for other reasons. In these situations, I like to step back and ask: What’s the simplest and most effective solution for my specific case?

From experience, I’ve learned that adding extra services should be a last resort. Every new service brings extra complexity — more to configure, more to maintain, and another potential point of failure. So if I can avoid deploying something new and still meet the requirements, I absolutely will.

When I had to scale out an application running a SignalR Hub, I needed to weigh the pros and cons of the solution Microsoft recommends. It’s a clean setup: by leveraging Redis’ pub/sub capabilities, you just initialize the backplane in your app through the provided official library, and SignalR takes care of syncing messages across instances. Simple and effective.

But I had to ask myself: Do I really need Redis for this low-throughput scenario? Is there a way to reuse services I’m already relying on — without spinning up yet another one, managing it, and paying for it? (Let’s be honest, throwing a simple Redis container into production would be risky in terms of reliability.)

Since PostgreSQL was already my primary database, I started looking into its LISTEN/NOTIFY functionality. While it has some limitations, it can act as a basic pub/sub system—enough to support an event-driven setup, which is exactly what I needed. Of course, I knew it wouldn’t be plug-and-play. I’d need to build some custom logic to handle persistent connections and reconnections. But even with that, it felt like a promising direction — definitely worth a shot.

How Did It End Up?

After spending some time building a background worker in my ASP.NET Core app to maintain a long-lived connection to PostgreSQL, I found that the solution not only worked — it was actually quite efficient. By setting up triggers at the database level, I was able to move the notification logic closer to where the changes happen, which helped keep concerns nicely separated.

All the app had to do was update or insert a record, and the rest took care of itself. Other instances could simply listen for notifications and forward the relevant messages to connected clients through SignalR. Below a graphical representation of how clients connected to different servers can be notified about changes requested by one of them.

PostgreSQL Backplane

As already said, this approach had the advantage of not requiring the deployment of additional services — a win in the long run. However, it also meant I had to take care of certain responsibilities myself.

With reusability in mind and the potential to leverage this work across other projects, I decided to build my own library: PostgreSQL.ListenNotify— a lightweight, MIT-licensed tool that abstracts away the complexity of working with PostgreSQL’s LISTEN/NOTIFY feature.

My goal with this library was to make it easily reusable with minimal setup, not only in association with SignalR, but with the idea of making it more general purpose. Getting started is simple: just register the service and hook up a few event handlers to begin receiving notifications.

Limitations to Keep in Mind

While we’ve seen why this can be a good solution in some scenarios, it’s important to also highlight when it might be better to opt for a more robust, battle-ready messaging system — especially for production-grade applications.

I’d recommend avoiding PostgreSQL as a message broker if your application has requirements like:

  • High throughput: PostgreSQL isn’t designed for high-volume messaging. If you’re dealing with thousands of messages per second or need millisecond delivery, Redis backplane may be more appropriate.
  • Message Durability: Notifications in PostgreSQL are not persisted. If a listener goes down, it misses messages.
  • Large-scale horizontal scalability: PostgreSQL isn’t built for horizontal scaling in the same way Redis is.

Still, for many systems, you do not need to deal with these problems.

References


Is Redis Overkill? Rethink SignalR Backplane with PostgreSQL was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.


This content originally appeared on Level Up Coding – Medium and was authored by Stefano Giannattasio