EverTask.Storage.Sqlite
3.9.0
See the version list below for details.
dotnet add package EverTask.Storage.Sqlite --version 3.9.0
NuGet\Install-Package EverTask.Storage.Sqlite -Version 3.9.0
<PackageReference Include="EverTask.Storage.Sqlite" Version="3.9.0" />
<PackageVersion Include="EverTask.Storage.Sqlite" Version="3.9.0" />
<PackageReference Include="EverTask.Storage.Sqlite" />
paket add EverTask.Storage.Sqlite --version 3.9.0
#r "nuget: EverTask.Storage.Sqlite, 3.9.0"
#:package EverTask.Storage.Sqlite@3.9.0
#addin nuget:?package=EverTask.Storage.Sqlite&version=3.9.0
#tool nuget:?package=EverTask.Storage.Sqlite&version=3.9.0

Overview
EverTask runs background work in your .NET app: fire-and-forget jobs, delayed and scheduled tasks, and recurring schedules. Everything is persisted, so tasks survive a restart.
It runs in-process (no external scheduler, no Windows Service, no separate worker host), and it doesn't poll the database in a loop. An in-memory scheduler drives execution through channels, and persistence happens where it matters: on enqueue, on status changes, and for recovery after a restart.
If you've used MediatR, the request/handler pattern will feel familiar. The difference is that tasks are persisted, can be isolated across queues, and hold up under load.
Tasks can be CPU-bound or I/O-bound, long- or short-running. Works with ASP.NET Core, Windows Services, or any .NET host.
Key Features
Core execution
- Background execution — fire-and-forget, scheduled, and recurring tasks
- No database polling — the scheduler lives in memory and runs through channels; the database is written, not polled in a loop
- Persistence — tasks resume after a restart (SQL Server, PostgreSQL, SQLite, In-Memory)
- Fluent scheduling — recurring tasks by minute, hour, day, week, month, or cron
- Idempotent registration — a task key keeps duplicate recurring registrations out
Performance & scalability
- Multi-queue — isolate workloads by priority, resource type, or business domain
- Keyed rate limiting — throttle per tenant/account/resource against external API limits, without blocking workers or other keys
- Light scheduler — minimal lock contention, zero CPU when idle
- Sharded scheduler — optional, for high scheduling load
- Lower overhead — reflection caching and lazy serialization
Monitoring
- Dashboard + REST API — an embedded React UI for monitoring and analytics
- Real-time updates — SignalR push with event-driven cache invalidation
- Execution log capture — a proxy logger with optional database persistence and configurable retention
- Audit levels — tune how much audit history you keep, to control table growth
Resilience
- Retry policies — built-in linear retry, custom policies, Polly integration, exception filtering
- Timeouts — global and per-task
Developer experience
- Extensible — custom storage, retry policies, and schedulers
- Serilog integration — structured logging
- Async throughout
<img src="assets/screenshots/4.png" style="width:100%;max-width:900px;display: block; margin:20px auto;" alt="Task Details" />
Quick Start
Installation
dotnet add package EverTask
dotnet add package EverTask.Storage.SqlServer # Or EverTask.Storage.Postgres / EverTask.Storage.Sqlite
Configuration
// Register EverTask with SQL Server storage
builder.Services.AddEverTask(opt =>
{
opt.RegisterTasksFromAssembly(typeof(Program).Assembly);
})
.AddSqlServerStorage(builder.Configuration.GetConnectionString("EverTaskDb"));
Create Your First Task
Define a task request:
public record SendWelcomeEmailTask(string UserEmail, string UserName) : IEverTask;
Create a handler:
public class SendWelcomeEmailHandler : EverTaskHandler<SendWelcomeEmailTask>
{
private readonly IEmailService _emailService;
public SendWelcomeEmailHandler(IEmailService emailService)
{
_emailService = emailService;
}
public override async Task Handle(SendWelcomeEmailTask task, CancellationToken cancellationToken)
{
Logger.LogInformation("Sending welcome email to {Email}", task.UserEmail);
await _emailService.SendWelcomeEmailAsync(
task.UserEmail,
task.UserName,
cancellationToken);
}
}
Dispatch the task:
// Send welcome email in background
await _dispatcher.Dispatch(new SendWelcomeEmailTask(dto.Email, dto.Name));
Documentation
📚 Full Documentation - Complete guides, tutorials, and API reference
Quick Links
- Getting Started - Installation, configuration, and your first task
- Task Creation - Requests, handlers, lifecycle hooks, and best practices
- Task Dispatching - Fire-and-forget, delayed, and scheduled tasks
- Recurring Tasks - Fluent scheduling API, cron expressions, idempotent registration
- Resilience & Error Handling - Retry policies, timeouts, CancellationToken usage
- Monitoring - Complete monitoring guide (Dashboard, Events, and Logs)
- Scalability - Multi-queue support, keyed rate limiting, and sharded scheduler for high-load scenarios
- Task Orchestration - Chain tasks, build workflows, and coordinate complex processes
- Storage Configuration - SQL Server, PostgreSQL, SQLite, In-Memory, custom implementations
- Configuration - Configure EverTask (Reference + Cheatsheet)
- Architecture & Internals - How EverTask works under the hood
A closer look
Fluent Recurring Scheduler
Schedule recurring tasks with a type-safe API:
// Run every day at 3 AM
await dispatcher.Dispatch(
new DailyCleanupTask(),
builder => builder.Schedule().EveryDay().AtTime(new TimeOnly(3, 0)));
// Run every Monday, Wednesday, Friday at 9 AM (for 30 days)
var days = new[] { DayOfWeek.Monday, DayOfWeek.Wednesday, DayOfWeek.Friday };
await dispatcher.Dispatch(
new BackupTask(),
builder => builder.Schedule().EveryWeek().OnDays(days).AtTime(new TimeOnly(9, 0)).RunUntil(DateTimeOffset.UtcNow.AddDays(30)));
Multi-Queue Workload Isolation
Keep critical tasks separate from heavy background work:
// High-priority queue for critical operations
.AddQueue("critical", q => q
.SetMaxDegreeOfParallelism(20)
.SetChannelCapacity(500)
.SetDefaultTimeout(TimeSpan.FromMinutes(2)))
Retry policies with exception filtering
Control which exceptions trigger retries to fail-fast on permanent errors:
// Predefined sets for common scenarios
RetryPolicy => new LinearRetryPolicy(5, TimeSpan.FromSeconds(2)).HandleTransientDatabaseErrors();
// Whitelist: Only retry specific exceptions (you can also use DoNotHandle for blacklist)
RetryPolicy = new LinearRetryPolicy(3, TimeSpan.FromSeconds(1)).Handle<DbException>().Handle<HttpRequestException>();
// Predicate: Custom logic (e.g., HTTP 5xx only)
RetryPolicy = new LinearRetryPolicy(3, TimeSpan.FromSeconds(1)).HandleWhen(ex => ex is HttpRequestException httpEx && httpEx.StatusCode >= 500);
Keyed Rate Limiting
Throttle tasks against external API limits (per tenant, per account, per resource) without slowing anyone else down:
public record SyncTenantData(Guid TenantId) : IEverTask, IRateLimitedTask
{
public string RateLimitKey => TenantId.ToString();
}
public class SyncTenantDataHandler : EverTaskHandler<SyncTenantData>
{
// Each tenant gets 15 calls per minute — other tenants are unaffected
public override RateLimitPolicy? RateLimitPolicy =>
new RateLimitPolicy(15, TimeSpan.FromMinutes(1));
public override Task Handle(SyncTenantData task, CancellationToken ct) => ...;
}
When a task exceeds its key's budget, EverTask reserves the next available slot and re-schedules it automatically: no worker is blocked, no task is dropped, and tasks for other keys keep flowing. Rate limiting is in-memory and per-instance (a pluggable seam for distributed limiters is on the roadmap).
Idempotent Task Registration
Use unique keys to safely register recurring tasks at startup without creating duplicates:
// Register recurring tasks - safe to call on every startup
await _dispatcher.Dispatch(
new DailyCleanupTask(),
r => r.Schedule().EveryDay().AtTime(new TimeOnly(3, 0)),
taskKey: "daily-cleanup"); // Won't create duplicates
⚠️ Self-redispatch gotcha: while a handler is executing, its task is
InProgress. A dispatch with the same key as anInProgresstask is a no-op that returns the existing ID without scheduling anything (a warning is logged). If a handler re-dispatches itself (e.g. polling chains), use a null or per-attempt key like"my-task-{id}-{attempt}"; reserve stable keys for dispatches originating outside the handler.
Monitoring Dashboard
Monitor tasks from a built-in web dashboard with live status, task history, execution logs, and analytics:
Dashboard Preview:
<div align="center"> <table> <tr> <td align="center" width="20%"> <img src="assets/screenshots/1.png" width="100%" alt="Dashboard Overview" /> <br /> <em>Dashboard Overview</em> </td> <td align="center" width="20%"> <img src="assets/screenshots/3.png" width="100%" alt="Task List" /> <br /> <em>Task List with Filters</em> </td> <td align="center" width="20%"> <img src="assets/screenshots/4.png" width="100%" alt="Task Details" /> <br /> <em>Task Details & History</em> </td> <td align="center" width="20%"> <img src="assets/screenshots/6.png" width="100%" alt="Execution Logs" /> <br /> <em>Execution Logs Viewer</em> </td> <td align="center" width="20%"> <img src="assets/screenshots/8.png" width="100%" alt="Execution Logs" /> <br /> <em>Realtime flow</em> </td> </tr> </table>
📸 View all 10 screenshots in the documentation
</div>
Task Execution Log Capture
Capture all logs written during task execution and persist them to the database for debugging and auditing. Built-in retention (a time window plus a per-task cap) keeps log growth bounded for long-running and recurring tasks:
<img src="assets/screenshots/5.png" style="width:100%;max-width:900px;display: block; margin:20px auto;" alt="Task Details" /> <br /> <em>View logs in dashboard or retrieve via storage</em>
Quick Links
📦 NuGet Packages
- EverTask - Core library
- EverTask.Abstractions - Lightweight interfaces package
- EverTask.Storage.SqlServer - SQL Server storage
- EverTask.Storage.Sqlite - SQLite storage
- EverTask.Storage.Postgres - PostgreSQL storage
- EverTask.Storage.EfCore - EF Core base storage
- EverTask.Logging.Serilog - Serilog integration
- EverTask.Monitor.AspnetCore.SignalR - Real-time monitoring
- EverTask.Monitor.Api - Monitoring API and Dashboard
📝 Resources
- Changelog - Version history and release notes
- Attribution - Acknowledgements and license information
- GitHub Repository - Source code and issues
- Examples - Sample applications (ASP.NET Core, Console)
Roadmap
On the roadmap:
- Task Management API: REST endpoints for stopping, restarting, and canceling tasks via the dashboard
- Distributed Clustering: Multi-server task distribution with leader election and automatic failover
- Distributed Rate Limiting: Redis-based keyed limiter sharing budgets across instances (the in-process keyed rate limiting shipped in 3.7.0; the
IKeyedRateLimiterDI seam is ready) - Adaptive Throttling: Dynamic throttling based on system resources
- Workflow Orchestration: Complex workflow and saga orchestration with fluent API
- Additional Monitoring: Sentry Crons, Application Insights, OpenTelemetry support
- More Storage Options: MySQL, Redis, Cosmos DB (PostgreSQL shipped)
Contributing
Contributions are welcome! Bug reports, feature requests, and pull requests all help make EverTask better.
- Report issues: https://github.com/GiampaoloGabba/EverTask/issues
- Contribute code: https://github.com/GiampaoloGabba/EverTask/pulls
License
EverTask is licensed under the Apache License 2.0.
See ATTRIBUTION.md for acknowledgements and attributions.
Developed with ❤️ by Giampaolo Gabba
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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 is compatible. 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 is compatible. 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. |
-
net10.0
- EverTask (>= 3.9.0)
- EverTask.Storage.EfCore (>= 3.9.0)
- Microsoft.EntityFrameworkCore.Relational (>= 10.0.9)
- Microsoft.EntityFrameworkCore.Sqlite (>= 10.0.9)
- Microsoft.EntityFrameworkCore.Tools (>= 10.0.9)
- System.Security.Cryptography.Xml (>= 10.0.9)
- UUIDNext (>= 4.2.4)
-
net8.0
- EverTask (>= 3.9.0)
- EverTask.Storage.EfCore (>= 3.9.0)
- Microsoft.EntityFrameworkCore.Relational (>= 8.0.28)
- Microsoft.EntityFrameworkCore.Sqlite (>= 8.0.28)
- Microsoft.EntityFrameworkCore.Tools (>= 8.0.28)
- System.Security.Cryptography.Xml (>= 8.0.3)
- UUIDNext (>= 4.2.4)
-
net9.0
- EverTask (>= 3.9.0)
- EverTask.Storage.EfCore (>= 3.9.0)
- Microsoft.EntityFrameworkCore.Relational (>= 9.0.17)
- Microsoft.EntityFrameworkCore.Sqlite (>= 9.0.17)
- Microsoft.EntityFrameworkCore.Tools (>= 9.0.17)
- System.Security.Cryptography.Xml (>= 9.0.17)
- UUIDNext (>= 4.2.4)
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 |
|---|---|---|
| 3.10.0 | 0 | 6/17/2026 |
| 3.9.0 | 25 | 6/16/2026 |
| 3.6.0 | 51 | 6/11/2026 |
| 3.5.0 | 209 | 1/11/2026 |
| 3.4.4 | 132 | 1/11/2026 |
| 3.4.3 | 131 | 1/10/2026 |
| 3.4.2 | 133 | 1/10/2026 |
| 3.4.1 | 129 | 1/10/2026 |
| 3.4.0 | 133 | 1/10/2026 |
| 3.3.0 | 263 | 11/7/2025 |
| 3.2.0 | 249 | 11/4/2025 |
| 3.1.2 | 246 | 11/2/2025 |
| 3.1.1 | 181 | 11/1/2025 |
| 3.0.0 | 227 | 10/19/2025 |
| 2.0.0 | 241 | 10/19/2025 |
| 1.5.4 | 301 | 5/31/2024 |
| 1.5.3 | 259 | 5/23/2024 |
| 1.5.2 | 270 | 4/9/2024 |
| 1.5.1 | 349 | 12/6/2023 |