<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Aot | The .NET Blog</title><link>https://thedotnetblog.com/tags/aot/</link><description>Articles, tutorials and insights from the .NET community.</description><generator>Hugo</generator><language>en</language><managingEditor>@thedotnetblog (The .NET Blog)</managingEditor><webMaster>@thedotnetblog</webMaster><lastBuildDate>Thu, 15 Jan 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://thedotnetblog.com/tags/aot/index.xml" rel="self" type="application/rss+xml"/><item><title>Single-File Apps in .NET 10</title><link>https://thedotnetblog.com/tutorials/emiliano-montesdeoca/single-file-apps-dotnet-10/</link><pubDate>Thu, 15 Jan 2026 00:00:00 +0000</pubDate><author>Emiliano Montesdeoca</author><guid>https://thedotnetblog.com/tutorials/emiliano-montesdeoca/single-file-apps-dotnet-10/</guid><description>How to build, publish, and optimize single-file executables with .NET 10 — from a basic console app to a trimmed, AOT-compiled binary.</description><content:encoded>&lt;p&gt;Single-file publishing has been part of .NET since version 5, but .NET 10 takes it to a new level with improved ahead-of-time (AOT) compilation, better trimming analysis, and smaller default output sizes. This tutorial walks you through publishing a real app as a single binary — no install required on the target machine.&lt;/p&gt;
&lt;h2 id="prerequisites"&gt;Prerequisites&lt;/h2&gt;
&lt;ul&gt;
&lt;li&gt;.NET 10 SDK installed (&lt;code&gt;dotnet --version&lt;/code&gt; should show &lt;code&gt;10.x.x&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;A console or ASP.NET Core app to work with&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="step-1-create-a-new-console-app"&gt;Step 1: Create a new console app&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet new console -n SingleFileDemo
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;cd&lt;/span&gt; SingleFileDemo
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="step-2-publish-as-a-single-file"&gt;Step 2: Publish as a single file&lt;/h2&gt;
&lt;p&gt;The minimal publish command for a self-contained single-file app:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet publish -c Release -r linux-x64 &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; --self-contained &lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -p:PublishSingleFile&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="nb"&gt;true&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; -o ./output
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Replace &lt;code&gt;linux-x64&lt;/code&gt; with your target runtime identifier (&lt;code&gt;win-x64&lt;/code&gt;, &lt;code&gt;osx-arm64&lt;/code&gt;, etc.). The &lt;code&gt;--self-contained true&lt;/code&gt; flag bundles the .NET runtime into the output binary.&lt;/p&gt;
&lt;p&gt;After publishing, &lt;code&gt;./output/&lt;/code&gt; contains a single executable file.&lt;/p&gt;
&lt;h2 id="step-3-add-trimming"&gt;Step 3: Add trimming&lt;/h2&gt;
&lt;p&gt;Trimming removes unreachable code from the final binary, often cutting size by 60–80%:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c"&gt;&amp;lt;!-- Add to your .csproj --&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;PublishSingleFile&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/PublishSingleFile&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;SelfContained&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/SelfContained&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;PublishTrimmed&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/PublishTrimmed&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;TrimMode&amp;gt;&lt;/span&gt;full&lt;span class="nt"&gt;&amp;lt;/TrimMode&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Then just run:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;dotnet publish -c Release -r linux-x64 -o ./output
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id="step-4-native-aot-optional-but-powerful"&gt;Step 4: Native AOT (optional but powerful)&lt;/h2&gt;
&lt;p&gt;For the smallest and fastest binaries, use Native AOT instead of single-file:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-xml" data-lang="xml"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nt"&gt;&amp;lt;PublishAot&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/PublishAot&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Native AOT compiles your app to native machine code at publish time. There&amp;rsquo;s no JIT at runtime, which means near-instant startup and a much smaller memory footprint.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; Native AOT doesn&amp;rsquo;t support all reflection patterns. Run &lt;code&gt;dotnet publish&lt;/code&gt; once and review any AOT compatibility warnings before committing to this approach.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;h2 id="checking-binary-size"&gt;Checking binary size&lt;/h2&gt;
&lt;div class="highlight"&gt;&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-bash" data-lang="bash"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;ls -lh ./output/
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="c1"&gt;# -rwxr-xr-x 1 user staff 12M SingleFileDemo&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;With trimming + AOT on a simple console app, expect 5–15 MB depending on dependencies.&lt;/p&gt;
&lt;h2 id="wrapping-up"&gt;Wrapping up&lt;/h2&gt;
&lt;p&gt;Single-file publishing in .NET 10 is production-ready for most workloads. Start with &lt;code&gt;PublishSingleFile=true&lt;/code&gt;, add trimming once your app is stable, and consider Native AOT if startup time or binary size are hard constraints.&lt;/p&gt;</content:encoded></item></channel></rss>