Delta for Database-Aware HTTP 304 Responses
An approach to implementing a 304 Not Modified leveraging DB change tracking
At a glance
- What is it?
- Delta is a C# library that turns database update timestamps into HTTP ETags for 304 Not Modified responses. It is aimed at applications whose data changes less often than it is read, with SQL Server, PostgreSQL, raw DbConnection, and Entity Framework integration paths.
- Who is it for?
- Delta suits read-heavy applications whose database changes infrequently and whose responses can be safely represented by an ETag. It is a poor fit for frequently changing data, deployments without a reliable database timestamp, or teams that need a documented rollback procedure.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 6 days ago.
- What is it written in?
- Mainly C#, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.
Editorial analysis
Delta's Database-Backed ETag Model
Delta addresses a specific HTTP caching problem: a server can avoid sending an unchanged response body when the client already has a representation identified by a matching ETag. Instead of treating every dynamic request as uncacheable, Delta obtains a last-updated timestamp from the database and uses it as part of the ETag. When the client sends a matching `If-None-Match` value, the response path can return 304 Not Modified.
The library assumes that updates to data occur relatively infrequently compared with reads. That assumption matters because Delta reduces repeated payload transfer only when the representation remains unchanged for long enough. It is therefore most relevant to read-heavy data that users revisit, such as records that are edited occasionally but queried often.
The README presents Delta as a way to reduce server load while allowing consumers to receive current data. That claim is conditional on the database timestamp accurately changing when the represented data changes, and on clients applying HTTP cache rules correctly. Delta does not describe itself as a general-purpose cache replacement. It is an application-level mechanism for deriving validators from database state.
What Delta Puts Inside an ETag
Delta calculates each ETag from three parts. The documented format is `{AssemblyWriteTime}-{DbTimeStamp}-{Suffix}`. The assembly component records the last write time of the web entry point assembly. The database component is supplied by the target database implementation. The suffix is optional and can be calculated at runtime from the current `HttpContext`.
The assembly timestamp is obtained from the entry assembly location and its file write time. Delta converts the ticks value to a string so it can be combined with the other ETag components. This allows a deployed web application to produce a different validator after a new build, without requiring a separate version field.
The database timestamp is the part that represents changing data. The README links to database-specific documentation for SQL Server and PostgreSQL rather than presenting one universal query. That separation is important because timestamp calculation is not portable across database systems. The suffix exists for cases where one database row or query does not fully determine the response. The documented example uses `UseDelta` and a callback returning `"MySuffix"`.
Delta then wraps the combined value as an ETag. If the suffix is absent, the output contains the assembly timestamp and database timestamp. If it is present, the suffix is appended after a hyphen. This makes the validator composition inspectable, but it also means that an application must choose a suffix that does not collide between materially different responses.
Cache-Control and 304 Decision Flow
The documented request flow first checks whether the request contains `no-cache` in `Cache-Control`. If it does, Delta obtains a fresh database timestamp. Otherwise, the flow checks for `max-age` or `max-stale`. When those directives exist, the cached timestamp is evaluated against the permitted staleness, including `min-fresh`. A cached timestamp may be used when it remains acceptable under those rules.
Delta then calculates the current ETag using either the cached timestamp or the fresh SQL timestamp. The response logic examines `If-None-Match`. A matching ETag produces 304 Not Modified. A missing header, or a value that does not match, leads to the current ETag being added to the response and the normal response path continuing.
This flow gives cache directives a role beyond simple boolean validation. A request that explicitly demands fresh data avoids reusing the cached timestamp. By contrast, a request with directives that permit a stale representation may avoid the fresh database lookup. The README does not document configuration for tuning this policy, and it does not claim that Delta replaces an HTTP cache or CDN.
The architecture also has a narrow dependency. The timestamp lookup is database-specific, while the HTTP flow and ETag composition are shared. A deployment using a database not covered by the documented integrations would need an implementation that follows the same contract. The repository documentation directs readers to SQL Server and PostgreSQL implementations, so those are the confirmed paths.
Raw DbConnection and Entity Framework Usage
Delta offers two documented usage models. The raw `DbConnection` approach delivers functionality through `DbConnection` and `DbTransaction`. The associated NuGet package is `Delta`. This option is relevant when an application manages database access directly or does not use Entity Framework.
The Entity Framework approach uses `Delta.EF`. The README provides separate documentation for Entity Framework with SQL Server and Entity Framework with PostgreSQL. This split reflects provider-specific concerns, including how the relevant database timestamp is obtained and how the EF integration exposes the database state.
There is a provider-specific package shown in the README for SQL Server, named `Delta.SqlServer`. The repository links these packages through NuGet, while the main README directs readers to provider documentation for implementation details. The README does not show a complete installation command or a complete application registration example, so the exact package installation and service wiring cannot be reconstructed from the displayed documentation.
For an initial evaluation, start with the package matching the application's data access model and database provider, then follow the linked provider document for the timestamp query. Confirm that the generated ETag changes after the represented data changes. That verification is more informative than merely checking that an ETag header appears, because the whole caching decision depends on the database value being a meaningful change signal.
A Minimal ETag Registration Example
The README gives a concrete registration example for adding a runtime suffix. It shows that Delta can be applied to the application pipeline and that the suffix is computed through a callback receiving the current HTTP context.
var app = builder.Build();
app.UseDelta(suffix: httpContext => "MySuffix");This is a configuration example, not a complete application. The surrounding application builder, service registrations, and provider-specific database setup are not included in the README. Delta's package and provider documentation must supply those missing pieces.
The example makes one integration decision visible. A suffix is useful when the response depends on request-specific state beyond the database timestamp. The suffix is not optional decoration in the ETag format when configured. It becomes part of the validator, so changing it can change cache behavior even if the database timestamp and assembly write time remain identical.
The documented ETag builder shows the exact composition behavior:
internal static string BuildEtag(string timeStamp, string? suffix)
{
if (suffix == null)
{
return $"\"{AssemblyWriteTime}-{timeStamp}\"";
}
return $"\"{AssemblyWriteTime}-{timeStamp}-{suffix}\"";
}The quotes are included in the returned value, which is consistent with an HTTP entity-tag representation. The method accepts the timestamp and an optional suffix, then combines them with `AssemblyWriteTime`. Applications should not copy the suffix example blindly if different routes or tenants can return different representations under the same database timestamp.
Where Delta Is the Wrong Choice
Delta is poorly matched to data that changes on nearly every request. Under that workload, the database timestamp can change frequently enough that validators do not produce many useful 304 responses. The project explicitly identifies low update frequency relative to reads as its central assumption.
It is also unsuitable when the database has no reliable change signal that maps to the response. A last-updated timestamp may exist at the database level without representing every field that the endpoint returns. Delta cannot make a stale representation current merely because the database contains a timestamp. Likewise, transformations, computed fields, related records, and authorization-specific output can make one timestamp insufficient unless the application handles those distinctions through the suffix or another design choice.
The README does not state a rollback procedure, cache invalidation API, multi-region coordination model, or behavior for every conflicting-update scenario. It also does not establish that every database provider is supported. Those omissions are relevant for teams considering Delta as a central cache consistency layer.
A conventional alternative is to compute or assign an application-level resource version whenever a resource changes, then use that version as the ETag. Delta instead derives the database timestamp directly and adds assembly and optional request context. An application that already has precise per-resource versioning may find that approach easier to reason about, while Delta reduces the need to maintain a separate version field. The choice depends on whether the database timestamp is a faithful representation of the endpoint's content.
Maintenance, License, and Upgrade Scope
The repository is not archived, and its last push was on 2026-10-14. The available release information lists version 8.1.0 dated 2026-03-12. The README directs readers to closed milestones for release notes, but it does not provide a compatibility matrix or an upgrade procedure.
The project is distributed under the MIT license. That identifies the repository's declared licensing model, but application owners still need to review how the package is distributed and whether its dependencies have separate license terms. Delta is a C# library with database-specific and Entity Framework-specific packages, so upgrading can involve coordinating the main package, provider package, and EF package rather than changing one dependency alone.
The repository layout includes source under `src` and documentation under `docs`. The README itself warns that it is generated from `readme.source.md`, which means editing the generated README is not the intended documentation workflow. For maintenance work, the relevant files are the provider documentation, package references, and source snippets that feed the README. No automated migration or rollback command is documented in the repository README.
Editorial conclusion
Delta suits read-heavy applications whose database changes infrequently and whose responses can be safely represented by an ETag. It is a poor fit for frequently changing data, deployments without a reliable database timestamp, or teams that need a documented rollback procedure. Verify first that the selected SQL Server or PostgreSQL integration produces a current timestamp and that application-specific suffixes distinguish responses correctly.
Frequently asked questions
What problem does SimonCropp/Delta solve?
Delta uses database change tracking to help ASP.NET applications produce HTTP 304 Not Modified responses through ETags. The README says it is intended for data that is read much more often than it is updated.
How does SimonCropp/Delta calculate an ETag?
Delta combines the web entry assembly's last write time, a database timestamp, and an optional suffix. The suffix can be calculated from the current `HttpContext`.
Which databases and data access models does SimonCropp/Delta support?
The README documents SQL Server and PostgreSQL implementations. It also documents raw `DbConnection` usage with `Delta` and Entity Framework usage with `Delta.EF`.
Official sources
Add this badge to your README
If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.
[](https://hysenlabs.com/projects/simoncropp-delta)Was this useful?