100% Free Forever
AI-Powered Learning
Industry Expert Content
Certificates & Badges
Learn At Your Own Pace
.NET

Publishing Single-File Apps

How .NET's single-file publishing bundles an app and its dependencies into one executable, how extraction and trimming work, and what caveats to expect.

Cross-Platform .NETIntermediate9 min readJul 10, 2026
Analogies

Publishing Single-File Apps

Publishing with dotnet publish -p:PublishSingleFile=true -r linux-x64 bundles your application's managed assemblies (and optionally native dependencies) into a single native executable for a specific RID, rather than producing a folder full of loose DLLs. This dramatically simplifies distribution, copying or shipping one file instead of managing a directory of dozens of dependency assemblies, and is commonly paired with a self-contained publish so the target machine needs nothing but that one file to run the app.

🏏

Cricket analogy: A touring squad checking in for a series with all kit consolidated into one oversized team trunk instead of forty individual bags simplifies logistics at every airport, similar to dotnet publish -p:PublishSingleFile=true bundling an app and its dependencies into one executable instead of a folder full of DLLs.

Extraction at Startup and Self-Contained vs Framework-Dependent

By default, a single-file app still extracts its bundled managed assemblies to a temporary directory on disk the first time (or every time, depending on caching settings) it runs, because the .NET runtime needs actual files on disk to memory-map and load; the 'single file' is really a self-extracting bundle format, not literal in-memory execution of everything without ever touching disk. Setting IncludeNativeLibrariesForSelfExtract controls whether native (non-managed) dependencies are also embedded and extracted, and self-contained single-file publishes differ from framework-dependent ones in that the former embeds the runtime itself while the latter still expects a compatible shared runtime already installed on the machine.

🏏

Cricket analogy: A team's equipment truck unpacks gear into designated zones at the stadium before the match can start, adding setup time before play begins, similar to a single-file app extracting its bundled DLLs to a temp directory before the process can actually run.

Combining Single-File with Trimming

Combining PublishTrimmed with single-file publishing reduces the final executable's size further by statically analyzing which code is actually reachable and removing everything else, which matters a lot for a bundle that's already carrying the whole runtime. This comes with real risk: trimming can't always prove that reflection-based code paths are reachable, so heavily reflection-driven libraries (some ORMs, some serializers, dependency injection containers using runtime type scanning) can break silently unless properly annotated or tested against the trimmed output; IncludeAllContentForSelfExtract additionally controls whether non-assembly content files get bundled into the single file too.

🏏

Cricket analogy: A touring squad trims its traveling party down to only essential players and support staff to reduce costs and logistics for a short white-ball series, similar to PublishTrimmed stripping unused code from a single-file .NET app to reduce its final size, at the risk of cutting something needed via reflection.

bash
dotnet publish -c Release -r linux-x64 --self-contained \
  -p:PublishSingleFile=true \
  -p:IncludeNativeLibrariesForSelfExtract=true \
  -p:PublishTrimmed=true

# csproj equivalent
# <PropertyGroup>
#   <RuntimeIdentifier>linux-x64</RuntimeIdentifier>
#   <SelfContained>true</SelfContained>
#   <PublishSingleFile>true</PublishSingleFile>
#   <IncludeNativeLibrariesForSelfExtract>true</IncludeNativeLibrariesForSelfExtract>
# </PropertyGroup>

Platform Caveats and What 'Single File' Really Means

Despite the name, a single-file publish doesn't always produce literally one file: debug symbols (.pdb) are excluded from the bundle by default, and depending on IncludeNativeLibrariesForSelfExtract and platform, some native libraries may still be deployed alongside the executable rather than embedded inside it. Behavior also differs meaningfully between Windows and Linux around how native dependencies are handled, and single-file publishing has historically had specific interactions and restrictions with ReadyToRun compilation that are worth checking against the current SDK's release notes before assuming a given combination of publish flags is supported.

🏏

Cricket analogy: Even a 'complete' touring squad still needs local ground staff and umpires provided by the host board that don't travel with the team, similar to how a 'single-file' .NET publish can still leave the .pdb debug symbols or certain native libraries as separate files unless explicitly configured otherwise.

You can control where a self-extracting single-file app unpacks its temporary files by setting the DOTNET_BUNDLE_EXTRACT_BASE_DIR environment variable, useful in locked-down container environments where the default temp path isn't writable, or when you want extracted files cleaned up from a predictable location.

Some antivirus and endpoint-protection software flags self-extracting single-file .NET executables as suspicious purely because of the self-extraction behavior, and the extraction step itself adds measurable cold-start overhead compared to a plain framework-dependent folder deployment. Benchmark this trade-off before assuming single-file publishing is a pure win for latency-sensitive workloads.

  • PublishSingleFile bundles an app's managed assemblies into one executable for a specific RID.
  • Single-file apps are typically self-extracting bundles; they still write files to a temp directory at startup by default.
  • IncludeNativeLibrariesForSelfExtract controls whether native dependencies are embedded in the bundle or left alongside it.
  • Self-contained single-file publishes embed the runtime itself; framework-dependent ones still need a compatible shared runtime installed.
  • Combining PublishTrimmed with single-file reduces size but risks breaking reflection-heavy dependencies.
  • Debug symbols (.pdb) are excluded from the single file by default even though the executable looks self-contained.
  • DOTNET_BUNDLE_EXTRACT_BASE_DIR controls where a self-extracting app unpacks itself, useful for locked-down containers.

Practice what you learned

Was this page helpful?

Topics covered

#NET#NETCoreStudyNotes#MicrosoftTechnologies#PublishingSingleFileApps#Publishing#Single#File#Apps#StudyNotes#SkillVeris