Build1 distinct publisher3 min readUpdated
A dev.to teardown puts the failure threshold at five thousand rows and one extra pod. The item it flags hardest turns out not to be an ORM default at all.
The Engineer · Build desk

Compiled by The EngineerSomething wrong?How this is made
Twelve rows in local development against five thousand in production is roughly a 400x difference in volume [1], and five thousand rows is still a table you could scroll through by hand. The other two triggers the dev.to post names are one extra replica and a request that gets cancelled halfway [2]. That is the useful part of the framing: none of these thresholds are large.
Note the asymmetry in how the author treats them. The only failure with a full mechanism attached is the deployment one, and it is not EF Core's doing. Calling `db.Database.Migrate()` at app startup with five pods booting together produces a half-migrated schema at 3am, discovered through an alert rather than a review comment, according to the post [10]. Do the arithmetic on that: one runner is needed, so four of the five pods are concurrently mutating a schema nobody asked them to touch [2]. On a K3s deployment where multiple replicas are the entire point, the author notes this is the normal startup path [12], which means the shortcut's failure mode is the default configuration and not an unlucky corner of it.
The replacement is a generated idempotent SQL script, reviewed, then applied in the deploy pipeline [9], run once by a single runner in an init container or pipeline stage [11]. The substantive change is not where the command lives. It is that a person reads the DDL before it executes, and exactly one process is holding the lock while it does. The companion rule is that merged migrations are append-only, so a bad one gets a successor rather than an edit [13].
The ORM-side items in the sample are handled by construction rather than by explanation. A `uint RowVersion` sits on the entity from the first commit as an optimistic concurrency token, mapped with `IsRowVersion()` in a configuration class rather than by attribute [4][8]. Timestamps are `DateTimeOffset` in UTC, rendered in the user's zone only at the edge [6], and the clock arrives as `TimeProvider` so a test can assert an exact value instead of "sometime around now" [7]. Keys are sequential GUIDv7 for index friendliness [5], with a unique index on `Slug` and a composite on `(PublishedAt, Id)` [15]. The author's stated reason for the UTC and clock choices is retrofit cost [6]. The concurrency token belongs in that same category on the same reasoning: it is a line in the first migration now, and a coordination problem across every existing write path later.
One honest gap. The excerpt supplied to us stops mid-signature in the controller's `Show` action and never mentions change tracking or `AsNoTracking` [16]. The read path appears only as a shape: `Index` returns a `PagedResult<PostDto>` and threads the cancellation token into the service call [14]. Projecting to a DTO is the only tracking-adjacent decision visible in the code, and the post does not argue for it.
What holds the list together is a difference in recovery cost. A missing token or an attribute-littered entity is repairable in a migration and a pull request. A schema half-altered by four racing pods is repairable at 3am. That ordering justifies the author flagging startup migrations hardest, even though it is the one item on his list that a code reviewer looking at C# would never see.
Follow any of these and your For You feed starts watching them — no settings page required.
Ranked by verification strength, evidence, and original report placement.
The author writes that most EF Core bugs he has seen in production are not from bad code but from code that looks right: it compiles, passes review, and works fine locally against a database with twelve rows in it.
The post says the code then hits a table with five thousand rows, or a second replica, or a request that gets cancelled halfway through, and falls over in a way nobody wrote a test for.
The post frames the mistakes as the default behaviour of EF Core when you do not opt out, or the default behaviour of a deployment when nobody thought about what five pods starting at the same time means.
The sample Post entity declares 'public uint RowVersion { get; set; }' commented as an optimistic concurrency token, and PostConfiguration maps it with b.Property(p => p.RowVersion).IsRowVersion().
The entity's Id is initialised with Guid.CreateVersion7(), annotated in the source as sequential and index-friendly.
The author stores timestamps as UTC DateTimeOffset and renders them in the user's timezone only at the edge, saying he does the same on ProcessHub with Asia/Tehran rendering, because 'what timezone is this in' is a much worse question to answer after the data already exists in three different formats; he calls this easy to skip and annoying to retrofit later.
Evidence-backed comparisons of source perspectives and observed adoption signals. Read the methodology
Which Builder, Operator, and Investor concerns the observed source mix emphasized—not a truth score.
Evidence, demonstrated adoption, hype gap, incentives, and confidence are assessed independently, each on its own current evidence. How these are measured.
Illustrative code, no measurement
Every prescriptive claim is directly visible in the post's own code listings and CLI commands, which is verifiable evidence of what the author recommends. But the load-bearing empirical claims — 'most EF Core bugs I've seen', the five-thousand-row failure threshold, the half-migrated database at 3am — rest on unquantified personal recollection with no benchmark, incident report, or second source. The supplied text is also truncated before the failure-mode catalogue completes.
Self-reported use only
The only adoption signal is the author describing his own two deployments — ProcessHub storing UTC and rendering Asia/Tehran, and a multi-replica K3s cluster where migrations run from a single runner. There is no third-party deployment, telemetry, download, or survey evidence in the supplied material, so adoption cannot be credited beyond one practitioner's disclosed practice.
Thresholds firmer than the evidence
Mildly overstated. The headline framing puts precise-sounding failure boundaries — five thousand rows, one extra replica, roughly a 400x jump from the twelve-row local database — on what is an unmeasured anecdote, and generalises to 'most EF Core bugs I've seen in production'. Against that, the hardest-flagged item is a genuinely well-founded operational hazard and the code prescriptions are conservative and self-evidencing, so the overstatement is in the quantified framing rather than in the substance of the advice.
Self-published with mild self-promotion
This is a self-published developer-platform post with the usual engagement incentive, and it twice routes credibility through the author's own projects — ProcessHub as the UTC-storage reference and his K3s cluster as the multi-replica case — without disclosure. There is no vendor sponsorship, product being sold, or commercial claim in the supplied text, so the incentive load is moderate rather than high.
Single truncated source
Confidence is moderate-low. What the post prescribes is unambiguous and largely verifiable inside its own listings, but there is exactly one publisher, no corroboration for any empirical assertion, no adoption data beyond self-report, and the supplied body is cut off mid-sentence — one ledger characterisation of that body (that AsNoTracking and change tracking go unmentioned) is contradicted by the text itself.
build
Your "Index Only Scan" Did 2,847 Heap Fetches: Covering Indexes Are a Vacuum Problem1 distinct publisher
build
Once the question needs a cube, you own the parser1 distinct publisher
build
A NetworkPolicy in another repo broke invoicing while every dashboard reported success1 distinct publisher
build
The optional EntityManager is the bug: moving the transaction boundary into AsyncLocalStorage1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 24, 2026