# Hangfire.Redis.StackExchange keeps a Hangfire storage on the client its author prefers

> Hangfire.Redis.StackExchange is a Hangfire storage backend for Redis built on the StackExchange.Redis client rather than the original Hangfire.Redis, with batch support, a configurable key prefix and tunable list sizes. It suits a .NET team already on Hangfire and Redis, and it depends on an upstream Hangfire.Redis that is no longer supported.

**marcoCasamento/Hangfire.Redis.StackExchange** — HangFire Redis storage based on original (and now unsupported) Hangfire.Redis but using lovely StackExchange.Redis client

- Repository: https://github.com/marcoCasamento/Hangfire.Redis.StackExchange
- Stars: 518 · Forks: 114
- Language: C#
- License: NOASSERTION
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/marcocasamento-hangfire-redis-stackexchange

## It is a storage plug-in, and the upstream it replaces is unsupported

The scope is narrow and the description is unusually honest about it. This is HangFire Redis storage based on HangFire.Redis but using the StackExchange.Redis client, and the description says it is based on the original, and now unsupported, Hangfire.Redis but using the lovely StackExchange.Redis client. So there are two facts to hold at once. The functionality is not new, it is the original storage's behaviour re-expressed against a different Redis client, and the original is no longer maintained. The reason someone would fork it is the client, not the storage model: StackExchange.Redis is the client the ecosystem moved to, with its own connection multiplexer, its own configuration model and its own release cadence. The repository layout reflects a small, focused port with a `Hangfire.Redis.StackExchange/` directory for the implementation, a `Hangfire.Redis.Tests/` directory for the tests, a solution file, a `Hangfire_Redis_StackExchange.snk` for strong naming, and a `License.md` at the root.

## Two NuGet packages, and the StrongName one is not actually signed

The package table lists two artefacts, and the second one carries a caveat that is worth reading before you pick. `Hangfire.Redis.StackExchange` is the main package and `Hangfire.Redis.StackExchange.StrongName` is the variant for projects that need a signed assembly. The note is explicit that, despite the name, `Hangfire.Redis.StackExchange.StrongName` is not signed because `Hangfire.Core` is not yet signed. That is a factual statement about a dependency rather than a choice by this project, and it means the strong-named variant gives you a strong-named assembly that wraps an unsigned core. The practical effect is that a project with a strong-name policy still has an unsigned dependency in the graph, so the policy is not satisfied end to end. The project page also points out a case where you have no choice about which package to use. If you are using the `Microsoft.Extensions.Caching.Redis` package you will need to use `Hangfire.Redis.StackExchange.StrongName` instead, because the former package requires `StackExchange.Redis.StrongName` instead of `StackExchange.Redis`, and a mismatch there is a binding failure at runtime rather than a compile error.

## Registering the storage takes a multiplexer and one call

The setup path is documented as a tutorial for Hangfire on Redis in an ASP.NET Core MVC project, and the first step is to install at least the `Hangfire.AspNetCore` and `Hangfire.Redis.StackExchange` packages. Then the bare minimum code in `Startup.cs` is this:

```cs
public class Startup
{
    public static ConnectionMultiplexer Redis;

    public Startup(IHostingEnvironment env)
    {
        // Other codes / configurations are omitted for brevity.
        Redis = ConnectionMultiplexer.Connect(Configuration.GetConnectionString("Redis"));
    }

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddHangfire(configuration =>
        {
            configuration.UseRedisStorage(Redis);
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseHangfireServer();
    }
}
```

The multiplexer is a static field on `Startup` and the storage is given that object rather than a connection string, which is the second of the library's four highlights: efficient use of Redis resources thanks to ConnectionMultiplexer. The official StackExchange.Redis documentation is cited for the recommendation to create one multiplexer for multiple reuse, and the multiplexer is the expensive object in this client, so the guidance is about connection churn rather than about this library specifically.

## RedisStorageOptions is where the prefix and the list sizes are set

The storage configuration lives in a `RedisStorageOptions` object, and the shape of that class is the contract you configure. The first parameter of the storage method accepts either your Redis connection string or a `ConnectionMultiplexer` object, and the second accepts `RedisStorageOptions`, whose properties as of version 1.7.0 are:

```cs
namespace Hangfire.Redis
{
    public class RedisStorageOptions
    {
        public const string DefaultPrefix = "{hangfire}:";

        public RedisStorageOptions();

        public TimeSpan InvisibilityTimeout { get; set; }
        public TimeSpan FetchTimeout { get; set; }
        public string Prefix { get; set; }
        public int Db { get; set; }
        public int SucceededListSize { get; set; }
        public int DeletedListSize { get; set; }
    }
}
```

Two of these are worth understanding rather than copying. The `Prefix` property defaults to `{hangfire}:`, and the documentation says it is highly recommended to set the Prefix property to avoid overlap with other projects that target the same Redis store. The braces in the default are there to keep the key namespace in one Redis Cluster hash slot, which is what makes the storage usable in a clustered deployment, and that is exactly why a project-specific prefix matters: two Hangfire instances on one Redis must not collide, and a shared default prefix makes them collide. The other two, `SucceededListSize` and `DeletedListSize`, are the customisation of the Succeeded and Failed lists size, another of the four highlights, and they let you cap how much history the storage keeps in Redis.

## Server options are mostly about how often the server wakes up

The second half of the tuning surface is `BackgroundJobServerOptions`, which the `app.UseHangfireServer()` call accepts as its first parameter. The class carries `ServerName`, `WorkerCount`, `Queues`, `ShutdownTimeout`, `SchedulePollingInterval`, `HeartbeatInterval`, `ServerTimeout`, `ServerCheckInterval`, `FilterProvider` and `JobActivator`. The interval options are the ones the documentation tells you to consider, because several of them may be manually set to longer intervals to reduce CPU load, and the defaults are named with their values. `SchedulePollingInterval` is by default set to 15 seconds, `HeartbeatInterval` is by default set to 30 seconds, and `ServerTimeout` and `ServerCheckInterval` are by default set to 5 minutes. The shape of the trade-off is clear from the numbers. A 15 second poll is how quickly a scheduled job is noticed, a 30 second heartbeat is how often the server records that it is alive, and the five minute server check is the watchdog that notices a server has gone away. On a busy Redis instance, a fleet of Hangfire servers polling every fifteen seconds is a steady background load, and lengthening those intervals is the documented way to reduce it. The cost is that a scheduled job may start up to the poll interval late, which is a reasonable trade for a background system and an unreasonable one if your schedule is precise.

## The dashboard needs an authorization filter, and the middleware order matters

The dashboard is where a storage plug-in becomes a security surface, and the documentation handles it in two steps. The first is an `IDashboardAuthorizationFilter` implementation that checks the current user:

```cs
public class AdministratorHangfireDashboardAuthorizationFilter : IDashboardAuthorizationFilter
{
    public bool Authorize(DashboardContext context)
    {
        var user = context.GetHttpContext().User;
        return user.Identity.IsAuthenticated && user.IsInRole("Administrator");
    }
}
```

The second is wiring it into the application pipeline, and the ordering note in the code is a real requirement rather than a style preference:

```cs
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
{
    app.UseCookieAuthentication(...);

    // This middleware must be placed AFTER the authentication middlewares!
    app.UseHangfireDashboard(options: new DashboardOptions
    {
        Authorization = new[] { new AdministratorHangfireDashboardAuthorizationFilter() }
    });
}
```

The comment in the snippet says the middleware must be placed after the authentication middlewares, and the reason is visible in the filter itself, since it reads the authenticated user off the HttpContext. If the dashboard middleware runs before authentication, the user is anonymous and the filter denies every request, which looks like a broken dashboard rather than a misconfiguration. The documentation also notes this snippet is a short version with limited access to cookie-authenticated users of the Administrator role, and points at the official Hangfire documentation for the fuller picture.

## Jobs can be defined as injected services rather than static methods

The last part of the tutorial covers how to define jobs, and it takes the dependency injection route for cleaner and more manageable application code. A job is defined in a class that is registered via dependency injection, and the project links the Microsoft documentation on that topic. The repository root shows a `Hangfire.Redis.Tests/` directory with the test suite and a `Hangfire.Redis.StackExchange.sln.DotSettings` file carrying the shared solution settings, alongside a `Makefile`-less build driven by the solution and an `appveyor.yml` for continuous integration. The visible documentation stops at the beginning of that example, so the details of how a job is registered and invoked are in the official Hangfire documentation rather than here. The four highlights listed in the project page are the whole of the feature claim: support for Hangfire Batches, which is a Hangfire Pro feature, the efficient use of Redis resources through the multiplexer, the Redis prefix allowing multiple Hangfire instances against a single Redis database, and the customisation of the Succeeded and Failed list sizes.

## Where a Redis storage plug-in is the wrong thing to reach for

Two limits are worth naming. The first is that this is a plug-in for a job system, so it is only useful if you have already decided that Hangfire is your job system, and Hangfire is not the only option for .NET background work. A team that has not chosen its background processing stack should choose that first, and this repository becomes one line of configuration rather than a decision. The second is the support chain, and the documentation states it plainly: the foundation is the original and now unsupported Hangfire.Redis. That means the behaviour you inherit is frozen at whatever state that project was in, and the client underneath is a maintained one. A project using a newer Hangfire major version may find that the storage surface it expects has moved, and the repository does not document a compatibility matrix. The alternative to weigh against is a newer storage implementation from the Hangfire project itself, which would carry upstream support at the cost of the client and the batch support this package offers. The difference in approach is who owns the long term. This project optimises the client and the features, and takes on the risk of a storage layer nobody upstream maintains, and that trade is worth making for a team that has already standardised on StackExchange.Redis and treats the prefix and the list sizes as things it needs to control.

## Conclusion

Hangfire.Redis.StackExchange is worth adopting if your .NET application already runs Hangfire and you would rather use StackExchange.Redis than the client the original storage shipped with, because the storage model is the same and the client swap is invisible to your jobs. It is a poor fit for a new project with no Hangfire dependency, since this is a storage plug-in and not a job system, and a poor fit if you need support from the Hangfire project itself, because the project describes its foundation as the original and now unsupported Hangfire.Redis. Before you adopt it, read `License.md` in the repository root, since the licence is a custom one that GitHub cannot classify, and check the Redis prefix you configure, because the project page calls it highly recommended to avoid overlap with other projects on the same Redis. The last push to the repository was on 2026-10-09.

## FAQ

### What does Hangfire.Redis.StackExchange do and how does it differ from Hangfire.Redis?

It is a HangFire Redis storage built on the original Hangfire.Redis but using the StackExchange.Redis client instead. The project description is explicit that the original Hangfire.Redis is now unsupported, so this package exists to keep the same storage behaviour while moving to the client the ecosystem uses.

### How do I register Hangfire with Redis in an ASP.NET Core MVC project?

Install the Hangfire.AspNetCore and Hangfire.Redis.StackExchange packages, create a static ConnectionMultiplexer in Startup and connect it to your Redis connection string, then call configuration.UseRedisStorage(Redis) inside services.AddHangfire and app.UseHangfireServer() in Configure.

### Why should I set the Prefix option in RedisStorageOptions?

The documentation calls it highly recommended, to avoid overlap with other projects that target the same Redis store. The default prefix is {hangfire}:, and two Hangfire instances sharing a Redis database would otherwise share key namespaces and collide, which matters in a clustered Redis where the braces keep keys in one hash slot.

### Is Hangfire.Redis.StackExchange.StrongName actually signed?

No. The project page states that despite the name, Hangfire.Redis.StackExchange.StrongName is not signed because Hangfire.Core is not yet signed. It is the package you need if you use Microsoft.Extensions.Caching.Redis, since that package requires StackExchange.Redis.StrongName rather than StackExchange.Redis.

## Sources

- [Issues](https://github.com/marcoCasamento/Hangfire.Redis.StackExchange/issues)
- [marcoCasamento/Hangfire.Redis.StackExchange on GitHub](https://github.com/marcoCasamento/Hangfire.Redis.StackExchange)
- [README](https://github.com/marcoCasamento/Hangfire.Redis.StackExchange/blob/master/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/marcocasamento-hangfire-redis-stackexchange
