SqliteStorage.Hangfire 1.1.1

dotnet add package SqliteStorage.Hangfire --version 1.1.1
                    
NuGet\Install-Package SqliteStorage.Hangfire -Version 1.1.1
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="SqliteStorage.Hangfire" Version="1.1.1" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="SqliteStorage.Hangfire" Version="1.1.1" />
                    
Directory.Packages.props
<PackageReference Include="SqliteStorage.Hangfire" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add SqliteStorage.Hangfire --version 1.1.1
                    
#r "nuget: SqliteStorage.Hangfire, 1.1.1"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package SqliteStorage.Hangfire@1.1.1
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=SqliteStorage.Hangfire&version=1.1.1
                    
Install as a Cake Addin
#tool nuget:?package=SqliteStorage.Hangfire&version=1.1.1
                    
Install as a Cake Tool

SqliteStorage.Hangfire

A lightweight, concurrency-safe SQLite storage for Hangfire, built on Microsoft.Data.Sqlite. No external database server required — point it at a file and go.

The package ships as SqliteStorage.Hangfire because the Hangfire.* ID prefix is reserved on nuget.org. The assembly and namespace carry the same name; the UseSqliteStorage() extension lives in the Hangfire namespace for discoverability.

GlobalConfiguration.Configuration.UseSqliteStorage("hangfire.db");

Why another SQLite storage?

The existing community SQLite storage keeps a shared, long-lived connection object that can be disposed while background timers (heartbeat, distributed lock cleanup, counters aggregator) still hold a reference to it. Under load — for example when the Hangfire.Console extension multiplies the number of storage writes per job — this use-after-dispose race surfaces as a stream of NullReferenceExceptions from HangfireDbContext, failed heartbeats and broken dashboard pages.

This storage is designed so that failure mode cannot exist:

  • No shared connection. Every operation opens a short-lived connection from the Microsoft.Data.Sqlite pool and disposes it when done. There is no shared mutable state to race on.
  • WAL mode + busy timeout. Readers never block the writer; write contention is absorbed by SQLite's busy handler plus a retry layer for the stragglers.
  • Atomic job fetch. Dequeueing is a single UPDATE … RETURNING statement — no SELECT-then-UPDATE race between workers.
  • Lease-based distributed locks. A PRIMARY KEY on the resource makes double-acquisition impossible; leases are extended by a heartbeat and expire on their own if the owner dies.
  • Crash-safe processing. Fetched jobs send keep-alive updates; if the process dies, the invisibility timeout returns the job to the queue.
  • Integer timestamps. All times are stored as Unix epoch milliseconds — no DateTime string parsing or timezone surprises.

Works with the dashboard, Hangfire.Console, recurring jobs, delayed jobs, retries, batches of parallel workers and multiple processes sharing the same database file.

Installation

dotnet add package SqliteStorage.Hangfire

Usage

ASP.NET Core

builder.Services.AddHangfire(configuration => configuration
    .SetDataCompatibilityLevel(CompatibilityLevel.Version_180)
    .UseSimpleAssemblyNameTypeSerializer()
    .UseRecommendedSerializerSettings()
    .UseSqliteStorage("hangfire.db"));

builder.Services.AddHangfireServer();

You can pass either a plain file path or a full Microsoft.Data.Sqlite connection string:

.UseSqliteStorage("Data Source=C:\\data\\hangfire.db")

Options

.UseSqliteStorage("hangfire.db", new SqliteStorageOptions
{
    QueuePollInterval = TimeSpan.FromSeconds(5),        // cross-process polling fallback
    InvisibilityTimeout = TimeSpan.FromMinutes(30),     // re-queue window after a hard crash
    DistributedLockLifetime = TimeSpan.FromSeconds(30), // lock lease length
    JobExpirationCheckInterval = TimeSpan.FromMinutes(30),
    CountersAggregateInterval = TimeSpan.FromMinutes(5),
    BusyTimeout = TimeSpan.FromSeconds(15)
})

In-process enqueues wake waiting workers immediately; QueuePollInterval only matters for jobs enqueued by other processes sharing the database file.

When to use this (and when not to)

SQLite is a single-file, single-writer database. This storage is a great fit for:

  • single-server applications, Windows services, desktop apps and IoT deployments;
  • small-to-medium workloads where installing PostgreSQL/SQL Server/Redis is not justified;
  • development and integration testing.

It is not a fit for multi-machine clusters — SQLite files should not be shared over network storage. If you outgrow a single machine, switch to one of the client-server storages; the Hangfire API stays the same.

Project layout

  • src/SqliteStorage.Hangfire — the storage library (netstandard2.0 + net8.0)
  • tests/SqliteStorage.Hangfire.Tests — unit tests plus an end-to-end test that runs a real BackgroundJobServer with Hangfire.Console under parallel load
  • samples/WebSample — ASP.NET Core sample with the dashboard, console output, recurring and delayed jobs

License

MIT

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 was computed.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.1.1 107 7/10/2026
1.1.0 100 7/10/2026
1.0.3 89 7/10/2026