Build1 distinct publisher2 min readUpdated
A dev.to guide prices 200-300ms of startup at roughly 30MB of binary plus the loss of reflection. That exchange rate favours functions that cold-start, not services that stay up.
The Engineer · Build desk
Compiled by The EngineerSomething wrong?How this is made
The publish flag is the cheap part. Native AOT is turned on in the publish command, alongside `--self-contained` and a runtime identifier [14], and Roslyn's output does not change at all: the IL emitted is identical, and every consequence arrives later, at ILCompiler and crossgen2 [12][2]. That asymmetry is why this is a trade and not a setting. The flag can be reverted in an afternoon. A codebase that has had reflection removed from it to survive tree-shaking cannot [1][9].
The steady state changes too, and not only in your favour. Under JIT, Tier 0 compiles everything at startup and Tier 1 re-optimises as code actually gets used [6]. Native AOT ships without a JIT, so that second pass never happens; crossgen2 does the optimising offline instead, reusing part of RyuJIT with more time than a runtime compiler can afford [3][11]. For a handler that runs hot for hours, trading profile-driven re-optimisation for a shorter first second is not obviously a gain [19].
The reflection restriction is decided at build time. ILCompiler traces reachability from `Main` and deletes what it cannot reach, so a method that is never called is simply absent from the executable [9]. When it meets `Type.GetType("MinhaClasse")` it cannot determine statically which type is meant, and the guide's author names that as the problem case [10]. What Native AOT removes is the forgiving half of the model: no runtime compiler is left to make a late decision about a type the linker has already dropped [17].
If the aim is only to cut startup work, ReadyToRun precompiles partially, keeps the runtime, and leaves the JIT available for whatever was not precompiled, which means reflection keeps working [7]. It is the option that "AOT by default" thinking skips, and the guide itself places full Native AOT at the aggressive end of the spectrum: extreme startup gains against rigid reflection restrictions [8]. Scope matters here as well, since the guide is written against .NET 9 and .NET 10 LTS with SDK 9.0 or newer [13].
The figure that settles the decision is not in the guide: how many process starts your service performs per deployed artifact.
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 qualifies the phrase "no .NET runtime" as not 100 percent accurate: parts of the standard library remain linked in, including GC, allocator and data structures, though dramatically reduced compared with JIT.
In the JIT model, the JIT takes the IL at application startup and turns it into machine code dynamically as the code runs, with the runtime including JIT, GC and libraries resident in memory.
Standard JIT Tier 0 compiles everything at startup, then Tier 1 optimises further according to usage.
ILCompiler detects problematic reflection: with Type.GetType("MinhaClasse"), the compiler cannot statically determine which type is wanted, which the author calls a problem.
In Native AOT, the toolchain on the build machine takes the IL, performs static analysis, removes unnecessary code (trimming) and produces native machine code (x86-64, ARM, etc.) before execution.
The Native AOT result is a standalone executable with no JIT, no interpreter and no embedded .NET runtime.
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.
Thin: one practitioner guide, mechanism described, numbers unmethodical
The cluster has a single source. Its architectural claims (Roslyn IL emission, ILCompiler reachability and tree-shaking, crossgen2/RyuJIT offline codegen, linking, R2R as partial AOT) are specific, internally consistent and self-supporting as an explanation of the documented toolchain. The load-bearing quantities are not: 200-300ms and +30MB appear as prose ranges with no workload, hardware, measurement method or benchmark output, and the guide's own hello-world example uses different magnitudes (~100MB JIT versus ~5MB AOT). No second publisher, no vendor documentation and no reproducible artifact are supplied.
No adoption evidence supplied
Nothing in the supplied material reports anyone shipping, deploying or measuring Native AOT in production. There are no usage disclosures, deployment accounts, benchmark runs, download or repository signals, and no named organisation. Version targeting (.NET 9 / .NET 10 LTS, SDK 9.0+) establishes availability, not uptake, so no adoption value can be assigned without inventing facts.
Modestly overstated: precise-sounding numbers on an unmethodical basis
Positive but small. The guide is unusually caveat-forward for the genre — it opens by rejecting the 'compact, ultra-fast, serverless-ready' expectation, walks back its own 'no .NET runtime' phrasing, and frames AOT as the most aggressive point on a spectrum rather than a default. The overstatement is in the arithmetic surface: a 200-300ms/+30MB exchange rate reads as measured when it is a rule of thumb, and the framing does not separate the once-per-start nature of the startup win from the permanent per-artifact size cost, which is where long-lived services get misled.
Low: self-published explainer, no vendor stake disclosed
The only incentive facts available are those visible in the source: an individually authored tutorial on a developer content platform whose stated motivation is correcting a common misunderstanding, with no product, sponsorship, employer or commercial offering named and nothing being sold. The residual pressure is engagement-driven — a quantified hook ('200-300ms for +30MB') travels better than 'it depends' — which is enough to explain unmethodical precision but not a commercial conflict.
Moderate on mechanism, low on numbers
Confidence splits by claim type. The compilation-pipeline and reflection-limitation claims are described with enough internal specificity to be relied on directionally, and the derived consequence — no JIT plus deleted unreachable code means no runtime resolution of a string-named type — follows from the source's own statements. Confidence in the quantitative tradeoff is low: single publisher, no methodology, inconsistent size figures, zero adoption corroboration and a truncated body. Overall this supports a decision frame, not a number to plan against.
build
EF Core's defaults pass code review, then meet the second replica1 distinct publisher
build
Microsoft ships an MIT-licensed agent kernel: policy rings, Ed25519 identity, kill switch1 distinct publisher
build
wmic is gone, and Node's process trees on Windows 11 now come back empty1 distinct publisher
build
Four control planes, one Postgres: a team's case against polyglot persistence1 distinct publisher
Distinct publishers with included, body-backed reporting in this cluster.
dev.to
1 article · August 24, 2026