tbbuck.Hangfire.Storage.SQLite
0.5.1-beta
dotnet add package tbbuck.Hangfire.Storage.SQLite --version 0.5.1-beta
NuGet\Install-Package tbbuck.Hangfire.Storage.SQLite -Version 0.5.1-beta
<PackageReference Include="tbbuck.Hangfire.Storage.SQLite" Version="0.5.1-beta" />
<PackageVersion Include="tbbuck.Hangfire.Storage.SQLite" Version="0.5.1-beta" />
<PackageReference Include="tbbuck.Hangfire.Storage.SQLite" />
paket add tbbuck.Hangfire.Storage.SQLite --version 0.5.1-beta
#r "nuget: tbbuck.Hangfire.Storage.SQLite, 0.5.1-beta"
#:package tbbuck.Hangfire.Storage.SQLite@0.5.1-beta
#addin nuget:?package=tbbuck.Hangfire.Storage.SQLite&version=0.5.1-beta&prerelease
#tool nuget:?package=tbbuck.Hangfire.Storage.SQLite&version=0.5.1-beta&prerelease
Hangfire.Storage.SQLite (tbbuck fork)
🔒 Why this fork exists
This is a security-maintained fork of raisedapp/Hangfire.Storage.SQLite. The original package pulls in a SQLite native engine (
SQLitePCLRaw.bundle_green→lib.e_sqlite3 2.1.11) that is affected by CVE-2025-6965 — a High-severity (CVSS 7.2) memory-corruption flaw in SQLite versions before 3.50.2.This fork removes that dependency and ships the patched SourceGear SQLite 3.50.4 engine instead, with no public API changes. It is published on NuGet as
tbbuck.Hangfire.Storage.SQLite, and additionally adds UTC timestamp views and an opt-in sliding invisibility timeout.
Overview
An Alternative SQLite Storage for Hangfire.
This project was created by abandonment Hangfire.SQLite storage (https://github.com/wanlitao/HangfireExtension), as an alternative to use SQLite with Hangfire.
Is production ready? Yes
Installation
Install the package from NuGet. It is published as a prerelease (it depends on the
prerelease sqlite-net-pcl 1.11.x that carries the patched SQLite engine), so include
prereleases when installing:
Install-Package tbbuck.Hangfire.Storage.SQLite -IncludePrerelease
or with the .NET CLI:
dotnet add package tbbuck.Hangfire.Storage.SQLite --prerelease
.NET Framework note: the patched SourceGear SQLite engine does not support
AnyCPUon .NET Framework. If you consume this package from a .NET Framework app, set an explicit<PlatformTarget>(x64orx86). Modern .NET (Core / 5+) consumers are unaffected — native assets are resolved per-RID automatically.
Usage
This is how you connect to an SQLite instance
GlobalConfiguration.Configuration.UseSQLiteStorage();
Example
services.AddHangfire(configuration => configuration
.UseSimpleAssemblyNameTypeSerializer()
.UseRecommendedSerializerSettings()
.UseSQLiteStorage());
Options
In the UseSQLiteStorage method you can use an instance of the Hangfire.Storage.SQLite.SQLiteStorageOptions class to specify some options of this plugin.
Below is a description of them:
Option |
Default Value |
|---|---|
| QueuePollInterval | TimeSpan.FromSeconds(15) |
| InvisibilityTimeout | TimeSpan.FromMinutes(30) |
| UseSlidingInvisibilityTimeout | false (see Sliding invisibility timeout) |
| DistributedLockLifetime | TimeSpan.FromSeconds(30) |
| JobExpirationCheckInterval | TimeSpan.FromHours(1) |
| CountersAggregateInterval | TimeSpan.FromMinutes(5) |
| AutoVacuumSelected | AutoVacuum.NONE, other options: AutoVacuum.Full or AutoVacuum.Incremental AutoVacumm Explained |
Querying timestamps directly (UTC views)
All DateTime columns in the Hangfire tables (ExpireAt, CreatedAt, FetchedAt,
LastHeartbeat) are stored as .NET DateTime ticks (100-nanosecond intervals since
0001-01-01), not Unix milliseconds. This is invisible when you go through the library,
but it is a footgun for ad-hoc SQL run directly against the database: comparing those
columns against a Unix timestamp never matches, so time-windowed queries silently return
lifetime totals instead of erroring.
To convert ticks to a Unix timestamp in raw SQL:
-- ticks -> ISO-8601 UTC text
datetime((ExpireAt - 621355968000000000) / 10000000.0, 'unixepoch', 'subsec')
For convenience, this fork also creates a read-only <Table>_utc companion view for
every table with timestamp columns. Each view exposes all of the original columns plus a
<Column>Utc alias holding the ISO-8601 UTC string. The underlying tables and the
library's own behaviour are unchanged — the views are purely a convenience for direct
querying, and existing databases gain them automatically on next startup.
-- instead of: SELECT ExpireAt FROM "Job" (raw ticks)
SELECT ExpireAtUtc, CreatedAtUtc FROM "Job_utc" WHERE ExpireAtUtc > '2026-01-01';
Sliding invisibility timeout
When a worker dequeues a job, the job is hidden from other workers for InvisibilityTimeout
(default 30 minutes). If a job runs longer than that, another worker can pick it up and run it
again — duplicate execution. Raising InvisibilityTimeout only delays recovery when a server
genuinely crashes.
Setting UseSlidingInvisibilityTimeout = true fixes this the same way Hangfire's SQL Server and
PostgreSQL providers do: while a worker holds a job, a background process periodically "slides" the
job's fetched timestamp forward. The job stays invisible for as long as the owning worker is alive,
and becomes available again shortly after the worker (or its process) dies — so you can use a much
lower InvisibilityTimeout safely with long-running jobs.
GlobalConfiguration.Configuration.UseSQLiteStorage("hangfire.db", new SQLiteStorageOptions
{
UseSlidingInvisibilityTimeout = true,
InvisibilityTimeout = TimeSpan.FromMinutes(5),
});
The keep-alive runs every InvisibilityTimeout / 5. It relies on the storage's background processes
running, so it has no effect on servers configured not to run them.
Thanks
This project is mainly based on Hangfire.LiteDB storage by @codeyu (https://github.com/codeyu/Hangfire.LiteDB)
License
This project is under MIT license. You can obtain the license copy here.
| Product | Versions 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 was computed. 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. |
-
.NETStandard 2.0
- Hangfire.Core (>= 1.8.23)
- Newtonsoft.Json (>= 13.0.4)
- sqlite-net-pcl (>= 1.11.272-beta)
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 |
|---|---|---|
| 0.5.1-beta | 105 | 6/24/2026 |
| 0.5.0-beta | 65 | 6/23/2026 |
0.5.1-beta (tbbuck fork)
- Fix AccessViolationException / storage corruption in SQLiteDistributedLock: the lock
heartbeat now runs on its own dedicated connection instead of sharing the caller's
non-thread-safe (NoMutex) connection (upstream issue #79).
0.5.0-beta (tbbuck fork)
- Security: remediate CVE-2025-6965 (SQLite < 3.50.2, High/CVSS 7.2) by dropping the
bundled SQLitePCLRaw.lib.e_sqlite3 2.1.11 native library.
- Replace sqlite-net-pcl 1.9.172 + SQLitePCLRaw.bundle_green 2.1.11 with sqlite-net-pcl
1.11.272-beta, which depends on SQLitePCLRaw.core 3.0.3 and ships the patched
SourceGear.sqlite3 3.50.4.5 native engine (SQLite 3.50.4).
- No public API changes; the ORM surface is unchanged.
0.4.3 (thanks to @itsC-Ramesh)
- Upgrade projects to .NET 8.0 (LTS).
- Update dependencies (Hangfire 1.8.23, Newtonsoft.Json 13.0.4).
- Explicitly referenced SQLitePCLRaw.bundle_green 2.1.11 to resolve NETSDK1206 RID-related warnings.
- Support for modern Hangfire 1.8 background process registration (GetStorageWideProcesses).