<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Oleksandr Shevchenko</title>
    <description>The latest articles on DEV Community by Oleksandr Shevchenko (@whitewaw).</description>
    <link>https://dev.to/whitewaw</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3618373%2F29e765eb-0bce-4d38-80cc-879c55dd3e9f.jpg</url>
      <title>DEV Community: Oleksandr Shevchenko</title>
      <link>https://dev.to/whitewaw</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/whitewaw"/>
    <language>en</language>
    <item>
      <title>Bundling NuGet Package Dependencies in an SSIS Script Task</title>
      <dc:creator>Oleksandr Shevchenko</dc:creator>
      <pubDate>Fri, 18 Sep 2026 16:03:12 +0000</pubDate>
      <link>https://dev.to/whitewaw/bundling-nuget-package-dependencies-in-an-ssis-script-task-57ad</link>
      <guid>https://dev.to/whitewaw/bundling-nuget-package-dependencies-in-an-ssis-script-task-57ad</guid>
      <description>&lt;h1&gt;
  
  
  Bundling NuGet Package Dependencies in an SSIS Script Task
&lt;/h1&gt;

&lt;p&gt;If you've ever tried to reference a NuGet package with its own dependency tree from inside an SSIS Script Task, you've probably hit the same wall: it works fine in Visual Studio, then falls over the moment the package runs from the command line on a server. This walkthrough shows how to fix that properly — referencing any NuGet package with dependencies in a Script Task and bundling those dependencies so the package runs correctly outside of Visual Studio, without relying on the embedded DLLs option. A private package, &lt;code&gt;Contoso.SampleLibrary&lt;/code&gt;, is used throughout as a concrete example.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Problem:&lt;/strong&gt; SSIS Script Tasks that reference NuGet packages fail to execute from the CLI.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Solution:&lt;/strong&gt; Temporarily point NuGet at the solution's packages folder, then use Costura.Fody to embed the required assemblies directly into the package.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Prerequisites
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;Visual Studio with the SSIS project open.&lt;/li&gt;
&lt;li&gt;Access to your organization's private NuGet package source.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Step 1: Temporarily update NuGet.Config
&lt;/h2&gt;

&lt;p&gt;Open &lt;code&gt;%AppData%\NuGet\NuGet.Config&lt;/code&gt; — the user-level NuGet configuration file — and temporarily add a &lt;code&gt;repositoryPath&lt;/code&gt; that points to the solution's packages folder.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Note:&lt;/strong&gt; &lt;code&gt;repositoryPath&lt;/code&gt; is resolved relative to the location of &lt;code&gt;NuGet.Config&lt;/code&gt;, not the solution directory, so it must be specified as an absolute path.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Info:&lt;/strong&gt; This update only redirects where packages are downloaded during script edit mode — from a temporary folder to a constant, persistent one. NuGet automatically resolves and chooses the proper compatible version of each library to incorporate into the solution.&lt;br&gt;
&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="cp"&gt;&amp;lt;?xml version="1.0" encoding="utf-8"?&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;config&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"repositoryPath"&lt;/span&gt; &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"C:\path\to\solution\packages"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/config&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;packageSources&amp;gt;&lt;/span&gt;
    &lt;span class="nt"&gt;&amp;lt;add&lt;/span&gt; &lt;span class="na"&gt;key=&lt;/span&gt;&lt;span class="s"&gt;"YourOrg.PrivateFeed"&lt;/span&gt;
         &lt;span class="na"&gt;value=&lt;/span&gt;&lt;span class="s"&gt;"https://pkgs.dev.azure.com/your-org/_packaging/YourOrg.PrivateFeed/nuget/v3/index.json"&lt;/span&gt;
         &lt;span class="na"&gt;protocolVersion=&lt;/span&gt;&lt;span class="s"&gt;"3"&lt;/span&gt; &lt;span class="nt"&gt;/&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;/packageSources&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;C:\path\to\solution\packages&lt;/code&gt; with the actual path to the solution's packages folder.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 2: Install the required packages
&lt;/h2&gt;

&lt;p&gt;In Visual Studio:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Right-click the Script Task project and select &lt;strong&gt;Manage NuGet Packages&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Choose your organization's private package source.&lt;/li&gt;
&lt;li&gt;Search for and install &lt;code&gt;Contoso.SampleLibrary&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Also install &lt;code&gt;Costura.Fody&lt;/code&gt;.&lt;/li&gt;
&lt;/ol&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Info:&lt;/strong&gt; Installing a package also pulls in its transitive dependencies automatically — see the summary below for how many packages this involves in this example.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Info:&lt;/strong&gt; Costura.Fody embeds all third-party libraries directly inside the &lt;code&gt;.dtsx&lt;/code&gt; file as binary resources, eliminating the need for an &lt;code&gt;AssemblyResolver&lt;/code&gt; or any additional custom classes within the Script Task project.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Because the DLLs are embedded as binary data in the &lt;code&gt;.dtsx&lt;/code&gt; file, the packages folder is only needed while editing the script in Visual Studio (script edit mode). On production/runtime servers, the packages folder is not required — everything needed is already embedded in the package.&lt;/p&gt;

&lt;p&gt;After installation, restart the Script Task project so it picks up the new DLLs from NuGet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Step 3: Clean up the temporary configuration
&lt;/h2&gt;

&lt;p&gt;Once the installation is complete, remove the temporary package source and &lt;code&gt;repositoryPath&lt;/code&gt; entries from:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;%AppData%\NuGet\NuGet.Config
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Warning:&lt;/strong&gt; These entries are only required for the one-time package restore and should not remain in the global NuGet configuration.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Summary
&lt;/h2&gt;

&lt;p&gt;In this example, NuGet downloads 19 packages (dependencies) together with &lt;code&gt;Contoso.SampleLibrary&lt;/code&gt;. No one would want to manually include all of them in an SSIS solution, especially since many of these packages contain multiple subfolders for different target runtimes and frameworks.&lt;/p&gt;

&lt;p&gt;Even if a manual approach were used, maintaining and updating all of these libraries in the future would become another challenge. By using a combination of &lt;code&gt;NuGet.Config&lt;/code&gt; and Costura.Fody, the SSIS solution can behave more like a traditional .NET application. This approach simplifies dependency management, automatically resolves compatible package versions and runtimes, and bundles the required assemblies, resulting in a more consistent and maintainable deployment model.&lt;/p&gt;

&lt;p&gt;Have you run into NuGet dependency headaches in SSIS Script Tasks, or found a different approach that works for you? Let me know in the comments.&lt;/p&gt;

</description>
      <category>nuget</category>
      <category>dotnet</category>
      <category>etl</category>
      <category>ssis</category>
    </item>
    <item>
      <title>SnapStart vs Native AOT: what actually happens to cold starts, warm latency, and your AWS bill</title>
      <dc:creator>Oleksandr Shevchenko</dc:creator>
      <pubDate>Fri, 18 Sep 2026 16:01:55 +0000</pubDate>
      <link>https://dev.to/whitewaw/snapstart-vs-native-aot-what-actually-happens-to-cold-starts-warm-latency-and-your-aws-bill-13ea</link>
      <guid>https://dev.to/whitewaw/snapstart-vs-native-aot-what-actually-happens-to-cold-starts-warm-latency-and-your-aws-bill-13ea</guid>
      <description>&lt;h1&gt;
  
  
  SnapStart vs Native AOT: what actually happens to cold starts, warm latency, and your AWS bill
&lt;/h1&gt;

&lt;p&gt;If you run .NET on AWS Lambda, you've probably faced this fork in the road: enable &lt;strong&gt;SnapStart&lt;/strong&gt; to shrink cold starts, or go all-in on &lt;strong&gt;Native AOT&lt;/strong&gt; and skip the .NET runtime entirely. Both promise faster cold starts. Only one of them, in my tests, actually delivered.&lt;/p&gt;

&lt;p&gt;I measured both configurations on the same 128 MB function shape, first with a couple of one-off samples, then with two proper batches (five cold requests and up to twelve warm requests per configuration), and finally ran the numbers through AWS's published pricing to see what it would cost at scale.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Spoiler: Native AOT won on cold latency, tied on warm latency, and won clearly on cost.&lt;/strong&gt; Here's the data.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;⚠️ &lt;strong&gt;Caveat up front:&lt;/strong&gt; SnapStart isn't available on the Native AOT managed runtime, so this comparison necessarily ran AOT on &lt;strong&gt;Amazon Linux 2023&lt;/strong&gt; and SnapStart on the &lt;strong&gt;.NET 10 (C#/F#/PowerShell)&lt;/strong&gt; managed runtime. That's a testing constraint, not a controlled experiment — the two configurations differ in more than just "SnapStart on or off." Treat this as directional evidence for this workload, not a universal verdict.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  TL;DR
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cold requests&lt;/strong&gt; (5 samples each): &lt;strong&gt;471.72 ms mean for AOT&lt;/strong&gt; vs &lt;strong&gt;849.43 ms for SnapStart&lt;/strong&gt; — AOT is &lt;strong&gt;44.5% faster&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;The gap is mostly first-execution, not snapshot restoration&lt;/strong&gt;: 81.7% of the cold-latency difference comes from the first handler invocation, not the restore step.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warm requests&lt;/strong&gt; (8 AOT / 12 SnapStart): AOT has the lower median (35.68 vs 39.50 ms), SnapStart has the slightly lower mean (53.67 vs 57.32 ms) — no clear warm-latency winner in these small samples.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Cost&lt;/strong&gt;: at 1M invocations/month and 1% cold starts, illustrative pricing puts AOT at &lt;strong&gt;$0.33/month&lt;/strong&gt; vs SnapStart at &lt;strong&gt;$0.98/month&lt;/strong&gt; per function — mostly because of SnapStart's caching and restoration fees, not compute.&lt;/li&gt;
&lt;li&gt;Numbers below are small-sample measurements and a pricing model, not a guarantee for your workload. Verify before deciding.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  1. Initial cold-start and single warm-request samples
&lt;/h2&gt;

&lt;p&gt;Both configurations use &lt;strong&gt;128 MB of allocated memory&lt;/strong&gt;. Native AOT was tested on the &lt;strong&gt;Amazon Linux 2023&lt;/strong&gt; managed runtime; SnapStart was tested on the &lt;strong&gt;.NET 10 (C#/F#/PowerShell)&lt;/strong&gt; managed runtime, since SnapStart is not available for the Native AOT runtime. This runtime difference is a testing constraint, not a controlled variable — the compared configurations differ in more than just SnapStart on/off.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Measurement&lt;/th&gt;
&lt;th&gt;SnapStart&lt;/th&gt;
&lt;th&gt;Native AOT&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Cold initialization / restoration&lt;/td&gt;
&lt;td&gt;346.09 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;267.41 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;First handler execution&lt;/td&gt;
&lt;td&gt;496.66 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;192.15 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Approximate cold-start total¹&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;842.75 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;459.56 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cold billed duration&lt;/td&gt;
&lt;td&gt;500 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;460 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Warm handler execution&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;9.41 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;36.82 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Warm billed duration&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;10 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;37 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum memory used&lt;/td&gt;
&lt;td&gt;55 MB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;50 MB&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;¹ Initialization/restoration plus execution; excludes API Gateway, client networking, and a separate authorizer.&lt;/p&gt;

&lt;h3&gt;
  
  
  Interpretation
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Cold request:&lt;/strong&gt; Native AOT was &lt;strong&gt;383.19 ms faster&lt;/strong&gt;. SnapStart took approximately &lt;strong&gt;83% longer&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Warm request:&lt;/strong&gt; SnapStart was &lt;strong&gt;27.41 ms faster&lt;/strong&gt;, approximately &lt;strong&gt;74% shorter&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Most of the cold-request difference came from &lt;strong&gt;handler execution&lt;/strong&gt;, not snapshot restoration:

&lt;ul&gt;
&lt;li&gt;Restoration versus initialization: &lt;strong&gt;78.68 ms difference&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;First handler execution: &lt;strong&gt;304.51 ms difference&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That first-execution difference deserves investigation. Network reconnection, downstream service latency, and first-use initialization are possible explanations—not conclusions established by these logs.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Important limitation:&lt;/strong&gt; these are one cold and one warm sample per configuration. They show what happened, but do not establish typical or p95 performance, or prove that SnapStart caused the warm improvement. Runtime/build details are based on the supplied deployment descriptions rather than independently established by these REPORT lines.&lt;/p&gt;

&lt;h3&gt;
  
  
  Source logs
&lt;/h3&gt;

&lt;p&gt;&lt;/p&gt;
  summary="Raw CloudWatch REPORT lines (initial single-request samples)"
  &lt;p&gt;SnapStart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REPORT RequestId: b23a929b-c7f9-404b-ad32-49210dad2fe0 Duration: 496.66 ms Billed Duration: 500 ms Memory Size: 128 MB Max Memory Used: 55 MB Restore Duration: 346.09 ms Billed Restore Duration: 3 ms
REPORT RequestId: fd64a0ca-b27b-4a58-bfab-06314199a0dc Duration: 9.41 ms Billed Duration: 10 ms Memory Size: 128 MB Max Memory Used: 55 MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Native AOT without SnapStart:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;REPORT RequestId: e2055d28-ce2e-4c69-ba09-df58c8efec4b Duration: 192.15 ms Billed Duration: 460 ms Memory Size: 128 MB Max Memory Used: 50 MB Init Duration: 267.41 ms
REPORT RequestId: 0513e1ac-1715-4ea4-bd87-f3d885ad0b44 Duration: 36.82 ms Billed Duration: 37 ms Memory Size: 128 MB Max Memory Used: 50 MB
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;br&gt;
&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Follow-up warm-request samples
&lt;/h3&gt;

&lt;p&gt;The additional batch contains &lt;strong&gt;8 Native AOT requests and 12 SnapStart requests&lt;/strong&gt;. None of these REPORT lines includes Init Duration or Restore Duration, so they are consistent with warm invocations. REPORT lines alone do not rule out a suppressed initialization after a failure.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;SnapStart (12 requests)&lt;/th&gt;
&lt;th&gt;Native AOT (8 requests)&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Median execution&lt;/td&gt;
&lt;td&gt;39.50 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;35.68 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mean execution&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;53.67 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;57.32 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Minimum execution&lt;/td&gt;
&lt;td&gt;30.59 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;23.71 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Maximum execution&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;181.04 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;199.86 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mean billed duration&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;54.25 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;57.625 ms&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reported maximum memory used&lt;/td&gt;
&lt;td&gt;55–58 MB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;50–53 MB&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Native AOT's median is &lt;strong&gt;3.825 ms lower&lt;/strong&gt;; SnapStart's median is approximately &lt;strong&gt;10.7% higher&lt;/strong&gt;. However, SnapStart's mean execution is &lt;strong&gt;6.4% lower&lt;/strong&gt;. Both datasets have slow observations that influence the means; all observations are retained. Max Memory Used is an execution-environment high-water mark, not an isolated measurement of memory consumed by each request.&lt;/p&gt;

&lt;p&gt;These results &lt;strong&gt;do not establish a consistent warm-execution winner&lt;/strong&gt;. They supersede the initial single-request warm comparison as the basis for the cost estimates below. Sample sizes are small and unequal, request equivalence has not been verified, and p95 estimates would be unstable.&lt;/p&gt;

&lt;p&gt;Durations and billed durations from the follow-up batch, in supplied order (milliseconds):&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  summary="Raw warm-batch data (20 requests)"
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AOT execution: 23.71, 199.86, 60.78, 38.82, 28.88, 44.28, 32.53, 29.66
AOT billed:    24, 200, 61, 39, 29, 45, 33, 30
Snap execution: 41.02, 33.65, 39.33, 181.04, 36.62, 40.43, 90.49, 39.67, 37.90, 41.12, 32.21, 30.59
Snap billed:    42, 34, 40, 182, 37, 41, 91, 40, 38, 42, 33, 31
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Follow-up cold-start samples (five per configuration)
&lt;/h3&gt;

&lt;p&gt;Each SnapStart RESTORE_REPORT repeats the Restore Duration shown in its corresponding REPORT; it is counted &lt;strong&gt;once&lt;/strong&gt;, not twice. Approximate Lambda-side cold latency is restoration or initialization plus handler execution, not billed duration.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Metric&lt;/th&gt;
&lt;th&gt;SnapStart&lt;/th&gt;
&lt;th&gt;Native AOT&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Mean restoration / initialization&lt;/td&gt;
&lt;td&gt;365.74 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;296.80 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mean first handler execution&lt;/td&gt;
&lt;td&gt;483.69 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;174.92 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Mean cold total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;849.43 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;471.72 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Median cold total&lt;/td&gt;
&lt;td&gt;827.50 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;440.35 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cold total minimum–maximum&lt;/td&gt;
&lt;td&gt;775.62–976.80 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;432.07–605.38 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Mean billed duration&lt;/td&gt;
&lt;td&gt;500.60 ms&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;472.40 ms&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Reported maximum memory used&lt;/td&gt;
&lt;td&gt;55 MB&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;50 MB&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Native AOT's mean cold latency is &lt;strong&gt;377.71 ms (44.5%) lower&lt;/strong&gt; than SnapStart's. Equivalently, SnapStart's mean cold latency is approximately &lt;strong&gt;80.1% higher&lt;/strong&gt; than AOT's. Even the slowest AOT cold request in this batch is faster than the fastest SnapStart cold request. This is descriptive evidence from five samples each, not a population-level guarantee or a matched-pair experiment.&lt;/p&gt;

&lt;p&gt;The mean gap has two components:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Restoration versus initialization: &lt;strong&gt;68.94 ms&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;First handler execution: &lt;strong&gt;308.77 ms&lt;/strong&gt;, accounting for approximately &lt;strong&gt;81.7%&lt;/strong&gt; of the total gap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The first-handler penalty is consistent across this batch: SnapStart executions range from &lt;strong&gt;460.01 to 500.75 ms&lt;/strong&gt;, versus &lt;strong&gt;149.83 to 212.37 ms&lt;/strong&gt; for AOT. This supports investigating first-use work, network reconnection, and downstream call timing rather than attributing the whole difference to restoration. These logs do not identify the cause or prove the deployed build types.&lt;/p&gt;

&lt;p&gt;Values in supplied order (milliseconds); totals combine fields within each request, not requests across configurations:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  summary="Raw cold-start batch data (10 requests)"
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Snap restore: 335.73, 333.19, 481.15, 363.02, 315.61
Snap execution: 491.77, 470.25, 495.65, 500.75, 460.01
Snap cold total: 827.50, 803.44, 976.80, 863.77, 775.62
Snap billed: 493, 509, 497, 502, 502
Snap billed restore: 1, 38, 1, 1, 41
AOT init: 277.92, 276.34, 282.24, 254.48, 393.01
AOT execution: 162.43, 164.18, 149.83, 185.78, 212.37
AOT cold total: 440.35, 440.52, 432.07, 440.26, 605.38
AOT billed: 441, 441, 433, 441, 606
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;p&gt;SnapStart's billed restore portion varies from &lt;strong&gt;1 to 41 ms&lt;/strong&gt;, while actual restoration takes &lt;strong&gt;315.61 to 481.15 ms&lt;/strong&gt;. A lower chargeable restore portion does not mean a faster response. Billed duration already includes that chargeable portion; do not add it again when calculating compute cost.&lt;/p&gt;

&lt;h3&gt;
  
  
  End-to-end Postman observations
&lt;/h3&gt;

&lt;p&gt;The user reports that Native AOT responds faster in Postman for both cold and warm requests. No numerical Postman timings were supplied, so this is a qualitative observation, not a measured percentage improvement. Postman includes client/network overhead, API Gateway, authorization, and the backend handler; a single Lambda Duration does not cover that entire path.&lt;/p&gt;

&lt;h2&gt;
  
  
  2. Pros and cons for this application
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Option&lt;/th&gt;
&lt;th&gt;Pros supported by these samples&lt;/th&gt;
&lt;th&gt;Cons / trade-offs&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Native AOT&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Lower cold latency across both supplied batches; lower follow-up warm median; lower reported memory use; no SnapStart fees; user reports faster Postman responses&lt;/td&gt;
&lt;td&gt;Slightly higher follow-up warm mean and one 199.86 ms observation; AOT requires compatible libraries and trimming configuration&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;SnapStart&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;Slightly lower follow-up warm mean and mean billed duration&lt;/td&gt;
&lt;td&gt;Higher follow-up warm median; slower cold samples and consistently longer first-handler execution in the new batch; snapshot caching and restoration fees; published-version management; still has cold restores&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;Neither provides guaranteed warm-like latency after idle periods.&lt;/strong&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  3. Long-term pricing assumptions
&lt;/h2&gt;

&lt;p&gt;The following estimates use rates published in the &lt;a href="https://aws.amazon.com/lambda/pricing/" rel="noopener noreferrer"&gt;AWS Lambda pricing example&lt;/a&gt;, reviewed on 2026-09-15:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Charge&lt;/th&gt;
&lt;th&gt;Rate used&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;x86 execution&lt;/td&gt;
&lt;td&gt;$0.0000166667 / GB-second&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Requests&lt;/td&gt;
&lt;td&gt;$0.20 / million&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET SnapStart caching&lt;/td&gt;
&lt;td&gt;$0.0000015046 / GB-second&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;.NET SnapStart restoration&lt;/td&gt;
&lt;td&gt;$0.0001397998 / GB restored&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;These are illustrative public example rates, not a verified Ohio-region quote:&lt;/strong&gt; the regional pricing lookup failed.&lt;/p&gt;

&lt;p&gt;Assumptions:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;One function, &lt;strong&gt;128 MB = 0.125 GB&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;One SnapStart version cached throughout a &lt;strong&gt;30-day month&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Cold durations use the five-request follow-up batch's mean billed duration: SnapStart 500.60 ms, AOT 472.40 ms. Warm durations use the warm follow-up batch's mean billed duration: SnapStart 54.25 ms, AOT 57.625 ms. Initial single cold and warm samples remain historical context and are not pooled into these estimates.&lt;/li&gt;
&lt;li&gt;These small samples are assumed representative only for illustration; they are not a reliable long-term traffic forecast.&lt;/li&gt;
&lt;li&gt;Both alternatives have the same invocation count and cold-start percentage.&lt;/li&gt;
&lt;li&gt;Each modeled cold SnapStart invocation corresponds to one snapshot restoration.&lt;/li&gt;
&lt;li&gt;Excludes discounts, deployment/snapshot-initialization compute, API Gateway, logs, and downstream services.&lt;/li&gt;
&lt;li&gt;Billing uses allocated memory, not maximum memory used.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Additional SnapStart fees at 128 MB
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Caching:&lt;/strong&gt; approximately &lt;strong&gt;$0.49/month per active version&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Restoration:&lt;/strong&gt; approximately &lt;strong&gt;$0.0175 per 1,000 restores&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;Seven functions with one cached version each: approximately &lt;strong&gt;$3.41/month&lt;/strong&gt;, or &lt;strong&gt;$41.52 per 365-day year&lt;/strong&gt;, for caching alone.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Old active versions can increase caching charges. Caching has a three-hour minimum per version.&lt;/p&gt;

&lt;p&gt;The logged &lt;code&gt;Billed Restore Duration: 3 ms&lt;/code&gt; contributes to ordinary duration billing; &lt;strong&gt;it does not replace the separate restoration fee&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Calculation model
&lt;/h3&gt;

&lt;p&gt;Let &lt;code&gt;N&lt;/code&gt; be monthly invocations and &lt;code&gt;f&lt;/code&gt; the fraction experiencing a cold start. Durations below are billed seconds and costs are USD.&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;
  summary="Show the full cost formulas"
  &lt;br&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;SnapStart compute = N × [f × 0.500600 + (1 − f) × 0.054250] × 0.125 × 0.0000166667
AOT compute       = N × [f × 0.472400 + (1 − f) × 0.057625] × 0.125 × 0.0000166667
Requests          = N × 0.20 / 1,000,000
SnapStart cache   = 0.125 × 2,592,000 × 0.0000015046
SnapStart restore = N × f × 0.125 × 0.0001397998

SnapStart total = SnapStart compute + Requests + SnapStart cache + SnapStart restore
AOT total       = AOT compute + Requests
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;




&lt;p&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  4. Estimated monthly cost
&lt;/h2&gt;

&lt;p&gt;Includes execution, requests, and applicable SnapStart fees.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Invocations per function/month&lt;/th&gt;
&lt;th&gt;Cold-start percentage&lt;/th&gt;
&lt;th&gt;SnapStart&lt;/th&gt;
&lt;th&gt;Native AOT&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;100,000&lt;/td&gt;
&lt;td&gt;0.1%&lt;/td&gt;
&lt;td&gt;$0.52&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.032&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100,000&lt;/td&gt;
&lt;td&gt;1%&lt;/td&gt;
&lt;td&gt;$0.54&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.033&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,000,000&lt;/td&gt;
&lt;td&gt;0.1%&lt;/td&gt;
&lt;td&gt;$0.82&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.32&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,000,000&lt;/td&gt;
&lt;td&gt;1%&lt;/td&gt;
&lt;td&gt;$0.98&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.33&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,000,000&lt;/td&gt;
&lt;td&gt;10%&lt;/td&gt;
&lt;td&gt;$2.64&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.41&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;At &lt;strong&gt;one million invocations/month and 1% cold starts&lt;/strong&gt;, twelve such 30-day months cost approximately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SnapStart: $11.81 per function&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Native AOT: $3.94 per function&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These are small absolute amounts at 128 MB, but multiply with function count, retained versions, and traffic. These per-function estimates should not be treated as per-API-request costs when each API request invokes both an authorizer and a handler.&lt;/p&gt;

&lt;h3&gt;
  
  
  Could SnapStart eventually be cheaper?
&lt;/h3&gt;

&lt;p&gt;Potentially, if its slightly lower mean warm billed duration holds across many requests. Under this updated model:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;With virtually no restores, roughly &lt;strong&gt;69.3 million invocations/month&lt;/strong&gt; are needed for warm-compute savings to offset caching.&lt;/li&gt;
&lt;li&gt;Above approximately &lt;strong&gt;0.040% cold invocations&lt;/strong&gt;, restoration fees and cold-duration differences outweigh those warm savings even before adding caching.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These thresholds are highly sensitive to the measured durations and assumed pricing.&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Project-level potential cost impact
&lt;/h2&gt;

&lt;p&gt;This compares &lt;strong&gt;Native AOT without SnapStart&lt;/strong&gt; against &lt;strong&gt;SnapStart enabled for seven Lambda functions&lt;/strong&gt;, using the supplied logs as a duration proxy. It is an estimate of the Lambda cost difference, not the project's entire AWS bill.&lt;/p&gt;

&lt;h3&gt;
  
  
  Project assumptions
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Seven functions, each allocated &lt;strong&gt;128 MB&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;One active cached version per function throughout a &lt;strong&gt;30-day month&lt;/strong&gt;: seven snapshots total.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;1% cold starts&lt;/strong&gt; in both scenarios.&lt;/li&gt;
&lt;li&gt;Mean billed durations from the supplied batches: &lt;strong&gt;472.40 ms cold / 57.625 ms warm without SnapStart&lt;/strong&gt;, versus &lt;strong&gt;500.60 ms cold / 54.25 ms warm with SnapStart&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;These durations are assumed to represent all seven functions; individual function timings have not been verified.&lt;/li&gt;
&lt;li&gt;Uses the illustrative pricing rates in section 3, excluding discounts and deployment/snapshot-initialization compute.&lt;/li&gt;
&lt;li&gt;Other infrastructure costs are excluded and assumed unchanged between scenarios.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Invocation counts below are totals across the project&lt;/strong&gt;, not per function and not API request counts. An API request invoking both a JWT authorizer and a backend function produces two Lambda invocations. Scheduled/background invocations also count toward the total.&lt;/p&gt;

&lt;h3&gt;
  
  
  Monthly project Lambda costs
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Total Lambda invocations/month&lt;/th&gt;
&lt;th&gt;Without SnapStart&lt;/th&gt;
&lt;th&gt;With SnapStart&lt;/th&gt;
&lt;th&gt;SnapStart extra/month&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;100,000&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.03&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$3.46&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;+$3.43&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;1,000,000&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.33&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$3.91&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;+$3.58&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10,000,000&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$3.29&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;$8.38&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;+$5.10&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;Totals and differences are rounded independently from unrounded calculations.&lt;/p&gt;

&lt;p&gt;At &lt;strong&gt;one million total project invocations/month&lt;/strong&gt;, twelve 30-day months cost approximately:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Without SnapStart: $3.94&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;With SnapStart: $46.91&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Additional SnapStart cost: $42.97&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Cost breakdown at one million project invocations/month
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cost component&lt;/th&gt;
&lt;th&gt;Without SnapStart&lt;/th&gt;
&lt;th&gt;With SnapStart&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Requests&lt;/td&gt;
&lt;td&gt;$0.200&lt;/td&gt;
&lt;td&gt;$0.200&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Execution&lt;/td&gt;
&lt;td&gt;$0.129&lt;/td&gt;
&lt;td&gt;$0.122&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Snapshot caching — seven versions&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;$3.412&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Snapshot restorations — 10,000 restores&lt;/td&gt;
&lt;td&gt;—&lt;/td&gt;
&lt;td&gt;$0.175&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;strong&gt;Total&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$0.33&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$3.91&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;The project's SnapStart caching component is &lt;strong&gt;7 × $0.4874904 = $3.4124328/month&lt;/strong&gt;. Execution, requests, and restoration charges use the project's total invocations only once; they are not multiplied by seven again. Retaining additional active versions increases caching charges.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Cost conclusion:&lt;/strong&gt; at 1% cold starts, the modeled warm-execution saving is less than one cent per million project invocations and does not offset SnapStart caching and restoration fees. The supplied logs therefore favor disabling SnapStart on cost as well as observed cold latency, subject to these assumptions. This is not a recommendation to change deployments without reviewing individual functions and retained versions.&lt;/p&gt;

&lt;h2&gt;
  
  
  6. Recommendation
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;The current evidence favors Native AOT for cold latency across both supplied batches, warm median, and modeled cost.&lt;/strong&gt; The five-request cold batch has mean totals of &lt;strong&gt;471.72 ms for AOT versus 849.43 ms for SnapStart&lt;/strong&gt;. The user also reports faster end-to-end Postman responses with Native AOT. SnapStart has a slightly lower follow-up warm mean, so these logs do not prove Native AOT is faster for every warm request.&lt;/p&gt;

&lt;p&gt;Before deciding permanently, compare identical requests and dependencies across multiple cold starts and warm runs, recording &lt;strong&gt;median and p95 total API latency&lt;/strong&gt;. Keep allocated memory, architecture, workload, and downstream configuration equivalent.&lt;/p&gt;

&lt;p&gt;In particular, investigate why first-handler execution averages &lt;strong&gt;483.69 ms with SnapStart versus 174.92 ms with AOT&lt;/strong&gt; in the five-request cold batch. This accounts for approximately &lt;strong&gt;81.7%&lt;/strong&gt; of the mean cold-latency gap. Correlate client timings with authorizer and backend request IDs, and instrument downstream calls before selecting a code-level optimization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closing thoughts
&lt;/h2&gt;

&lt;p&gt;For this workload, Native AOT beat SnapStart on cold latency, tied on warm latency, and came out cheaper once caching and restoration fees were modeled — without needing the extra moving parts of published versions and snapshot management. That said, the runtime mismatch noted above (Amazon Linux 2023 vs the .NET 10 managed runtime) means this isn't a clean, apples-to-apples benchmark, and five cold samples per configuration is a small dataset to build a permanent architectural decision on.&lt;/p&gt;

&lt;p&gt;If you're weighing the same trade-off: measure your own workload, watch what happens to that first post-restore invocation, and run the numbers through your actual traffic and cold-start rate before committing.&lt;/p&gt;

&lt;p&gt;Have you run a similar comparison, or seen different results with a heavier workload or larger memory allocation? I'd like to hear about it in the comments.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>dotnet</category>
      <category>lambda</category>
      <category>serverless</category>
    </item>
    <item>
      <title>.NET NativeAOT on AWS Lambda: 7 Faster Cold Starts, 73% Lower Costs</title>
      <dc:creator>Oleksandr Shevchenko</dc:creator>
      <pubDate>Thu, 04 Dec 2025 16:56:23 +0000</pubDate>
      <link>https://dev.to/whitewaw/net-nativeaot-on-aws-lambda-7x-faster-cold-starts-73-lower-costs-np3</link>
      <guid>https://dev.to/whitewaw/net-nativeaot-on-aws-lambda-7x-faster-cold-starts-73-lower-costs-np3</guid>
      <description>&lt;h1&gt;
  
  
  .NET NativeAOT on AWS Lambda: The Performance Revolution You've Been Waiting For
&lt;/h1&gt;

&lt;p&gt;If you're running .NET on AWS Lambda and haven't explored NativeAOT yet, you're leaving serious performance (and money) on the table. Let me show you some numbers that might change your mind:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚀 &lt;strong&gt;7× faster cold starts&lt;/strong&gt; (6680ms → 940ms)&lt;/li&gt;
&lt;li&gt;⚡ &lt;strong&gt;6× faster warm runs&lt;/strong&gt; (91ms → 14ms)&lt;/li&gt;
&lt;li&gt;💾 &lt;strong&gt;50% less memory&lt;/strong&gt; (93MB → 42MB)&lt;/li&gt;
&lt;li&gt;💰 &lt;strong&gt;73% lower costs&lt;/strong&gt; for high-volume workloads&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;And here's the kicker: &lt;strong&gt;these aren't theoretical numbers&lt;/strong&gt;. They're from real Lambda functions running in production.&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/whitewAw" rel="noopener noreferrer"&gt;
        whitewAw
      &lt;/a&gt; / &lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison" rel="noopener noreferrer"&gt;
        dotnet-lambda-aot-performance-comparison
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;.NET NativeAOT: Performance Revolution&lt;/h1&gt;
&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;A Deep Dive into AOT vs ReadyToRun vs Regular .NET&lt;/h2&gt;
&lt;/div&gt;
&lt;p&gt;&lt;a href="https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/70ac67dd5447f117d2b4ca6315c2ece13631baf8208eb7f92eb49de6c3589393/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5374616e645f576974682d556b7261696e652d4646443530303f6c6162656c436f6c6f723d303035424242" alt="Stand With Ukraine"&gt;&lt;/a&gt;
&lt;a href="https://github.com/whitewAw" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8d3e9c6de645ce42c7682244312136e24f71b5691e1726819732762d4b919dba/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446576656c6f7065645f62792d416c65785f2532384f6c656b73616e64722532395f536865766368656e6b6f2d3030363643433f6c6f676f3d676974687562" alt="Developed by"&gt;&lt;/a&gt;
&lt;a href="https://whitewaw.github.io/dotnet-lambda-aot-performance-comparison/performance-charts.html" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a8375c9d5a5ff77d3b61af0130d1849a961a0c6c66340bcf9d70293d81a81309/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4769744875625f50616765732d4c6976655f44656d6f2d3030643466663f6c6f676f3d676974687562" alt="GitHub Pages"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎬 Interactive Presentation&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📊 &lt;a href="https://whitewaw.github.io/dotnet-lambda-aot-performance-comparison/NativeAOT-Presentation.html" rel="nofollow noopener noreferrer"&gt;Interactive Slide Presentation&lt;/a&gt;&lt;/strong&gt; - Full visual presentation with charts, comparisons, and code examples.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;📈 &lt;a href="https://whitewaw.github.io/dotnet-lambda-aot-performance-comparison/performance-charts.html" rel="nofollow noopener noreferrer"&gt;Performance Charts&lt;/a&gt;&lt;/strong&gt; - Interactive charts showing all benchmark results.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📋 Table of Contents&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#introduction--objectives" rel="noopener noreferrer"&gt;Introduction &amp;amp; Objectives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#understanding-the-execution-models" rel="noopener noreferrer"&gt;Understanding the Execution Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#why-nativeaot-matters" rel="noopener noreferrer"&gt;Why NativeAOT Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#performance-results-the-numbers-dont-lie" rel="noopener noreferrer"&gt;Performance Results: The Numbers Don't Lie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#build--packaging-deep-dive" rel="noopener noreferrer"&gt;Build &amp;amp; Packaging Deep Dive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#coding-for-aot-patterns--best-practices" rel="noopener noreferrer"&gt;Coding for AOT: Patterns &amp;amp; Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#real-world-examples-from-this-repo" rel="noopener noreferrer"&gt;Real-World Examples from This Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#deployment-strategies" rel="noopener noreferrer"&gt;Deployment Strategies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#migration-guide" rel="noopener noreferrer"&gt;Migration Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#when-to-choose-which-approach" rel="noopener noreferrer"&gt;When to Choose Which Approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#faq--troubleshooting" rel="noopener noreferrer"&gt;FAQ &amp;amp; Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#key-takeaways" rel="noopener noreferrer"&gt;Key Takeaways&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#additional-resources" rel="noopener noreferrer"&gt;Additional Resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#getting-started" rel="noopener noreferrer"&gt;Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#contributing" rel="noopener noreferrer"&gt;Contributing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#license" rel="noopener noreferrer"&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#acknowledgments" rel="noopener noreferrer"&gt;Acknowledgments&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎯 Introduction &amp;amp; Objectives&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Who This Presentation Is For&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;.NET engineers familiar with Lambda, microservices, or performance-critical applications looking to understand modern compilation strategies.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;What You'll Learn&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NativeAOT fundamentals&lt;/strong&gt; and how it compares to ReadyToRun and Regular .NET&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measured performance improvements&lt;/strong&gt; from real-world Lambda functions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practical build and deployment&lt;/strong&gt; strategies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code&lt;/strong&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;h2&gt;
  
  
  Why Should You Care?
&lt;/h2&gt;

&lt;p&gt;Every second your Lambda function takes to cold start is a second your users wait. And in the world of web applications, &lt;strong&gt;every millisecond counts&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Amazon found that &lt;strong&gt;100ms delay = 1% revenue loss&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;Google reports &lt;strong&gt;53% of mobile users abandon sites taking &amp;gt;3 seconds to load&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;A 6.7-second cold start (Regular .NET) is simply &lt;strong&gt;unacceptable&lt;/strong&gt; for modern APIs&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;But it's not just about user experience - it's about &lt;strong&gt;your bottom line&lt;/strong&gt;:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Scale&lt;/th&gt;
&lt;th&gt;Regular .NET&lt;/th&gt;
&lt;th&gt;NativeAOT&lt;/th&gt;
&lt;th&gt;&lt;strong&gt;Savings&lt;/strong&gt;&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;1M requests/mo&lt;/td&gt;
&lt;td&gt;$0.98&lt;/td&gt;
&lt;td&gt;$0.26&lt;/td&gt;
&lt;td&gt;$0.72/mo&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;10M requests/mo&lt;/td&gt;
&lt;td&gt;$9.80&lt;/td&gt;
&lt;td&gt;$2.60&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$7.20/mo&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;100M requests/mo&lt;/td&gt;
&lt;td&gt;$98.00&lt;/td&gt;
&lt;td&gt;$26.00&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;$72/mo&lt;/strong&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;For an enterprise with 50 Lambda functions handling 100M requests each: &lt;strong&gt;$43,200/year saved&lt;/strong&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Three Compilation Modes: A Quick Primer
&lt;/h2&gt;

&lt;p&gt;Before we dive into the numbers, let's understand what we're comparing:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Regular .NET (JIT)
&lt;/h3&gt;

&lt;p&gt;Traditional approach: ships IL bytecode, compiles to native at runtime.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App Start → Load IL → Init Runtime → JIT Compile → Execute
                      ⏱️ SLOW      ⏱️ SLOW
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Maximum flexibility, smallest package&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Slowest startup, unpredictable performance&lt;/p&gt;
&lt;h3&gt;
  
  
  2. ReadyToRun (R2R)
&lt;/h3&gt;

&lt;p&gt;Hybrid: ships both IL and precompiled native images.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App Start → Load R2R+IL → Init Runtime → Execute (mostly native)
                          ⏱️ SLOW
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Faster startup than Regular, minimal code changes&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Still requires full runtime, larger packages&lt;/p&gt;
&lt;h3&gt;
  
  
  3. NativeAOT
&lt;/h3&gt;

&lt;p&gt;Pure native: everything compiled ahead-of-time.&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;App Start → Execute Native Binary
            ✅ FAST
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Pros:&lt;/strong&gt; Fastest startup, lowest memory, no runtime overhead&lt;br&gt;&lt;br&gt;
&lt;strong&gt;Cons:&lt;/strong&gt; Reflection limitations (requires source generators)&lt;/p&gt;
&lt;h2&gt;
  
  
  The Real Performance Data
&lt;/h2&gt;

&lt;p&gt;I built &lt;strong&gt;identical Lambda functions&lt;/strong&gt; in all three modes and ran them through hundreds of test cycles. Here's what I found:&lt;/p&gt;
&lt;h3&gt;
  
  
  Cold Start Performance
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Regular .NET 8:      ████████████████████████████████████████ 6680ms
ReadyToRun .NET 8:   ████████████████████████ 4389ms
AOT .NET 8:          ██████ 1082ms ⚡
AOT .NET 9:          █████ 971ms ⚡
AOT .NET 10:         ████ 940ms ⚡ (FASTEST)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Improvement: 7.1× faster&lt;/strong&gt; (Regular → AOT .NET 10)&lt;/p&gt;
&lt;h3&gt;
  
  
  Warm Run Performance
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ReadyToRun .NET 8:   ████████████ 99ms
Regular .NET 8:      ███████████ 91ms
AOT .NET 8:          ██ 18ms ⚡
AOT .NET 9:          █ 14ms ⚡ (FASTEST)
AOT .NET 10:         ██ 17ms ⚡
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Improvement: 6.5× faster&lt;/strong&gt; (Regular → AOT .NET 9)&lt;/p&gt;
&lt;h3&gt;
  
  
  Memory Usage
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ReadyToRun .NET 8:   ████████████ 89-96 MB
Regular .NET 8:      ███████████ 88-93 MB
AOT .NET 8:          █████ 46-52 MB ⚡
AOT .NET 9:          ████ 43-49 MB ⚡
AOT .NET 10:         ████ 42-48 MB ⚡ (LOWEST)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Improvement: 52% less memory&lt;/strong&gt; (Regular → AOT .NET 10)&lt;/p&gt;
&lt;h2&gt;
  
  
  The Code: What Changes?
&lt;/h2&gt;

&lt;p&gt;The good news? &lt;strong&gt;Your business logic doesn't change&lt;/strong&gt;. The differences are in how you bootstrap and serialize.&lt;/p&gt;
&lt;h3&gt;
  
  
  Regular .NET Lambda
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;assembly&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nf"&gt;LambdaSerializer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;DefaultLambdaJsonSerializer&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;

&lt;span class="k"&gt;namespace&lt;/span&gt; &lt;span class="nn"&gt;LambdaRegularDemo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Function&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IDynamoDBRepository&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDynamoDBRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;LambdaFunction&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;FunctionHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;ILambdaContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CancellationTokenSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemainingTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  NativeAOT Lambda
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;Main difference: Source-generated JSON serialization&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// AOTJsonContext.cs&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;JsonSerializable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;JsonSerializable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;))]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;AOTJsonContext&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;JsonSerializerContext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Function.cs&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;Function&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IDynamoDBRepository&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IDynamoDBRepository&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_repository&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repository&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="n"&gt;Task&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Guid&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;FunctionHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
        &lt;span class="n"&gt;ILambdaContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// Same business logic!&lt;/span&gt;
        &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;cts&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="nf"&gt;CancellationTokenSource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RemainingTime&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;_repository&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateAsync&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cts&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Token&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Program.cs - Custom runtime bootstrap&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;handler&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Dictionary&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ILambdaContext&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="k"&gt;using&lt;/span&gt; &lt;span class="nn"&gt;var&lt;/span&gt; &lt;span class="n"&gt;serviceProvider&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;CreateServiceProvider&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetRequiredService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Function&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;function&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;FunctionHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="n"&gt;LambdaBootstrapBuilder&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Create&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;handler&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;SourceGeneratorLambdaJsonSerializer&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;AOTJsonContext&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;())&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;RunAsync&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Project Configuration
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;The key difference is in your &lt;code&gt;.csproj&lt;/code&gt;:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight xml"&gt;&lt;code&gt;&lt;span class="nt"&gt;&amp;lt;PropertyGroup&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;OutputType&amp;gt;&lt;/span&gt;Exe&lt;span class="nt"&gt;&amp;lt;/OutputType&amp;gt;&lt;/span&gt; &lt;span class="c"&gt;&amp;lt;!-- Must be Exe for AOT --&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;TargetFramework&amp;gt;&lt;/span&gt;net9.0&lt;span class="nt"&gt;&amp;lt;/TargetFramework&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;RuntimeIdentifier&amp;gt;&lt;/span&gt;linux-x64&lt;span class="nt"&gt;&amp;lt;/RuntimeIdentifier&amp;gt;&lt;/span&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 class="c"&gt;&amp;lt;!-- Enable AOT --&amp;gt;&lt;/span&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 class="nt"&gt;&amp;lt;StripSymbols&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/StripSymbols&amp;gt;&lt;/span&gt;
  &lt;span class="nt"&gt;&amp;lt;InvariantGlobalization&amp;gt;&lt;/span&gt;true&lt;span class="nt"&gt;&amp;lt;/InvariantGlobalization&amp;gt;&lt;/span&gt;
&lt;span class="nt"&gt;&amp;lt;/PropertyGroup&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  The AOT Challenge: Reflection
&lt;/h2&gt;

&lt;p&gt;NativeAOT's biggest limitation? &lt;strong&gt;No dynamic reflection&lt;/strong&gt;. But this is actually a blessing in disguise - it forces you to write better code.&lt;/p&gt;
&lt;h3&gt;
  
  
  ❌ What Doesn't Work
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Dynamic type loading&lt;/span&gt;
&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"MyNamespace.MyClass"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;instance&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Activator&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;CreateInstance&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Runtime assembly loading&lt;/span&gt;
&lt;span class="n"&gt;Assembly&lt;/span&gt; &lt;span class="n"&gt;asm&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"PluginAssembly"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="c1"&gt;// Reflection-based serialization&lt;/span&gt;
&lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;obj&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// Uses reflection!&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  ✅ AOT-Friendly Alternatives
&lt;/h3&gt;

&lt;p&gt;&lt;strong&gt;1. JSON Source Generation&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nf"&gt;JsonSerializable&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;typeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;MyType&lt;/span&gt;&lt;span class="p"&gt;))]&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;partial&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyJsonContext&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;JsonSerializerContext&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Usage&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;JsonSerializer&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Serialize&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; 
    &lt;span class="n"&gt;MyJsonContext&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Default&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MyType&lt;/span&gt;
&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;2. Constructor Injection (Always!)&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ DO: Types known at compile time&lt;/span&gt;
&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;MyService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;private&lt;/span&gt; &lt;span class="k"&gt;readonly&lt;/span&gt; &lt;span class="n"&gt;IRepository&lt;/span&gt; &lt;span class="n"&gt;_repo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="nf"&gt;MyService&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;IRepository&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;_repo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ❌ DON'T: Service locator pattern&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serviceProvider&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetService&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IRepository&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;3. Explicit Type Registration&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="c1"&gt;// ✅ DO: Compile-time registration&lt;/span&gt;
&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ConcretePlugin1&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;
&lt;span class="n"&gt;services&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddSingleton&lt;/span&gt;&lt;span class="p"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;IPlugin&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ConcretePlugin2&lt;/span&gt;&lt;span class="p"&gt;&amp;gt;();&lt;/span&gt;

&lt;span class="c1"&gt;// ❌ DON'T: Runtime discovery&lt;/span&gt;
&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;plugins&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Directory&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;GetFiles&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"plugins"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"*.dll"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Select&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;Assembly&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;LoadFrom&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Building for Production
&lt;/h2&gt;

&lt;p&gt;Use Docker to ensure consistent Linux binaries:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;mcr.microsoft.com/dotnet/sdk:10.0&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="k"&gt;AS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s"&gt;build&lt;/span&gt;

&lt;span class="c"&gt;# Install native toolchain for AOT&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;apt-get update &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    apt-get &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;-y&lt;/span&gt; clang zlib1g-dev zip

&lt;span class="k"&gt;WORKDIR&lt;/span&gt;&lt;span class="s"&gt; /src&lt;/span&gt;
&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; . .&lt;/span&gt;

&lt;span class="c"&gt;# Build AOT Lambda&lt;/span&gt;
&lt;span class="k"&gt;RUN &lt;/span&gt;dotnet restore ./LambdaAOTDemo9/LambdaAOTDemo9.csproj &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    dotnet publish ./LambdaAOTDemo9/LambdaAOTDemo9.csproj &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nt"&gt;-c&lt;/span&gt; Release &lt;span class="nt"&gt;-o&lt;/span&gt; /artifacts/publish &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;mv&lt;/span&gt; /artifacts/publish/LambdaAOTDemo9 /artifacts/publish/bootstrap &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    &lt;span class="nb"&gt;cd&lt;/span&gt; /artifacts/publish &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="se"&gt;\
&lt;/span&gt;    zip &lt;span class="nt"&gt;-r&lt;/span&gt; /artifacts/LambdaAOTDemo9-lambda.zip .
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Why Docker?&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Ensures Linux build on any dev OS (Windows, Mac, Linux)&lt;/li&gt;
&lt;li&gt;Includes required native dependencies (&lt;code&gt;clang&lt;/code&gt;, &lt;code&gt;zlib1g-dev&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;Reproducible builds across team&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Deploying to AWS Lambda
&lt;/h2&gt;
&lt;h3&gt;
  
  
  Option 1: Custom Runtime (Recommended)
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;LambdaAOTFunction&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;Type&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;AWS::Lambda::Function&lt;/span&gt;
  &lt;span class="na"&gt;Properties&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;Runtime&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;provided.al2023&lt;/span&gt;
    &lt;span class="na"&gt;Handler&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;bootstrap&lt;/span&gt;
    &lt;span class="na"&gt;Code&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="na"&gt;S3Bucket&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="kt"&gt;!Ref&lt;/span&gt; &lt;span class="s"&gt;DeploymentBucket&lt;/span&gt;
      &lt;span class="na"&gt;S3Key&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;LambdaAOTDemo9-lambda.zip&lt;/span&gt;
    &lt;span class="na"&gt;MemorySize&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;256&lt;/span&gt;  &lt;span class="c1"&gt;# Can use less memory with AOT!&lt;/span&gt;
    &lt;span class="na"&gt;Timeout&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h3&gt;
  
  
  Option 2: Container Image
&lt;/h3&gt;


&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight docker"&gt;&lt;code&gt;&lt;span class="k"&gt;FROM&lt;/span&gt;&lt;span class="s"&gt; public.ecr.aws/lambda/provided:al2023&lt;/span&gt;

&lt;span class="k"&gt;COPY&lt;/span&gt;&lt;span class="s"&gt; --from=build /artifacts/publish/bootstrap ${LAMBDA_RUNTIME_DIR}/bootstrap&lt;/span&gt;

&lt;span class="k"&gt;CMD&lt;/span&gt;&lt;span class="s"&gt; ["bootstrap"]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;Benefits:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Deploy .NET 9, .NET 10, or future versions &lt;strong&gt;today&lt;/strong&gt;
&lt;/li&gt;
&lt;li&gt;No waiting for AWS managed runtime updates&lt;/li&gt;
&lt;li&gt;Smaller image (no 200MB+ .NET runtime layer)&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  When Should You Use AOT?
&lt;/h2&gt;
&lt;h3&gt;
  
  
  ✅ Choose NativeAOT When:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Cold start time is critical (APIs, webhooks, user-facing functions)&lt;/li&gt;
&lt;li&gt;Memory costs matter (high-volume serverless)&lt;/li&gt;
&lt;li&gt;Running .NET 9/10 on Lambda (managed runtime only supports .NET 8)&lt;/li&gt;
&lt;li&gt;Predictable performance required (SLA-driven workloads)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Perfect for:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;REST API backends&lt;/li&gt;
&lt;li&gt;Event processors (S3, SQS, EventBridge)&lt;/li&gt;
&lt;li&gt;GraphQL resolvers&lt;/li&gt;
&lt;li&gt;Scheduled tasks&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  ⚠️ Choose Regular .NET When:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;Maximum flexibility required (plugins, dynamic loading)&lt;/li&gt;
&lt;li&gt;Heavy reflection/dynamic code (complex ORMs, frameworks)&lt;/li&gt;
&lt;li&gt;Long-running processes (cold start amortized over lifetime)&lt;/li&gt;
&lt;li&gt;Fastest dev iteration&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;
  
  
  🔄 Choose ReadyToRun When:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;You want &lt;strong&gt;34% faster cold starts&lt;/strong&gt; with minimal code changes&lt;/li&gt;
&lt;li&gt;Testing AOT compatibility as a migration step&lt;/li&gt;
&lt;li&gt;Some dynamic features required&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;But remember:&lt;/strong&gt; R2R still costs &lt;strong&gt;300% more&lt;/strong&gt; than AOT!&lt;/p&gt;
&lt;h2&gt;
  
  
  The Business Case: Dual Value Proposition
&lt;/h2&gt;

&lt;p&gt;Quick responses aren't just a technical metric - they drive business value:&lt;/p&gt;
&lt;h3&gt;
  
  
  1. Lower Operating Costs
&lt;/h3&gt;

&lt;p&gt;At 100M requests/month:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Regular: $98/month per function&lt;/li&gt;
&lt;li&gt;AOT: $26/month per function&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Savings: $72/month&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With 50 functions: &lt;strong&gt;$43,200/year saved&lt;/strong&gt; 💰&lt;/p&gt;
&lt;h3&gt;
  
  
  2. Better User Experience
&lt;/h3&gt;

&lt;p&gt;At 100M requests/month, switching to AOT eliminates:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;2,138 hours&lt;/strong&gt; of cumulative user waiting time&lt;/li&gt;
&lt;li&gt;Calculation: (91ms - 14ms) × 100M requests = ~2,138 hours&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Translation:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Higher conversion rates&lt;/li&gt;
&lt;li&gt;Lower bounce rates&lt;/li&gt;
&lt;li&gt;Better SLA compliance&lt;/li&gt;
&lt;li&gt;Competitive advantage&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;
  
  
  Real-World Results
&lt;/h2&gt;

&lt;p&gt;Here's the complete performance table from my tests:&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;.NET&lt;/th&gt;
&lt;th&gt;Runtime&lt;/th&gt;
&lt;th&gt;Cold Start&lt;/th&gt;
&lt;th&gt;Warm Avg&lt;/th&gt;
&lt;th&gt;Memory&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Regular&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;dotnet8&lt;/td&gt;
&lt;td&gt;6680 ms&lt;/td&gt;
&lt;td&gt;91 ms&lt;/td&gt;
&lt;td&gt;88-93 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;ReadyToRun&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;dotnet8&lt;/td&gt;
&lt;td&gt;4389 ms&lt;/td&gt;
&lt;td&gt;99 ms&lt;/td&gt;
&lt;td&gt;89-96 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AOT&lt;/td&gt;
&lt;td&gt;8&lt;/td&gt;
&lt;td&gt;dotnet8&lt;/td&gt;
&lt;td&gt;1082 ms&lt;/td&gt;
&lt;td&gt;18 ms&lt;/td&gt;
&lt;td&gt;49-52 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AOT&lt;/td&gt;
&lt;td&gt;9&lt;/td&gt;
&lt;td&gt;dotnet8&lt;/td&gt;
&lt;td&gt;&lt;strong&gt;971 ms&lt;/strong&gt;&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;14 ms&lt;/strong&gt; ⚡&lt;/td&gt;
&lt;td&gt;47-49 MB&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;AOT&lt;/td&gt;
&lt;td&gt;10&lt;/td&gt;
&lt;td&gt;dotnet8&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;940 ms&lt;/strong&gt; ⚡&lt;/td&gt;
&lt;td&gt;17 ms&lt;/td&gt;
&lt;td&gt;
&lt;strong&gt;42-45 MB&lt;/strong&gt; ⚡&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;p&gt;&lt;strong&gt;.NET 10 AOT wins on cold start and memory&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
&lt;strong&gt;.NET 9 AOT wins on warm performance&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Getting Started
&lt;/h2&gt;

&lt;p&gt;Ready to try it yourself? Here's the quickest path:&lt;br&gt;
&lt;/p&gt;
&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone the demo repo&lt;/span&gt;
git clone https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison.git
&lt;span class="nb"&gt;cd &lt;/span&gt;dotnet-lambda-aot-performance-comparison

&lt;span class="c"&gt;# Build all Lambda packages via Docker&lt;/span&gt;
docker build &lt;span class="nt"&gt;-f&lt;/span&gt; src/Dockerfile &lt;span class="nt"&gt;-t&lt;/span&gt; aot-demo &lt;span class="nb"&gt;.&lt;/span&gt;

&lt;span class="c"&gt;# Extract artifacts&lt;/span&gt;
docker create &lt;span class="nt"&gt;--name&lt;/span&gt; temp aot-demo
docker &lt;span class="nb"&gt;cp &lt;/span&gt;temp:/artifacts ./build-output
docker &lt;span class="nb"&gt;rm &lt;/span&gt;temp

&lt;span class="c"&gt;# Deploy to AWS&lt;/span&gt;
aws s3 &lt;span class="nb"&gt;cp&lt;/span&gt; ./build-output/LambdaAOTDemo9-lambda.zip s3://your-bucket/
aws lambda update-function-code &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--function-name&lt;/span&gt; my-function &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--s3-bucket&lt;/span&gt; your-bucket &lt;span class="se"&gt;\&lt;/span&gt;
  &lt;span class="nt"&gt;--s3-key&lt;/span&gt; LambdaAOTDemo9-lambda.zip
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;h2&gt;
  
  
  Key Takeaways
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;NativeAOT is production-ready&lt;/strong&gt; for Lambda workloads&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;7× faster cold starts&lt;/strong&gt; and &lt;strong&gt;73% cost savings&lt;/strong&gt; are real&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code changes are minimal&lt;/strong&gt; (mostly serialization)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.NET 9/10 can run on Lambda today&lt;/strong&gt; via custom runtime&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;User experience AND cost&lt;/strong&gt; both improve dramatically&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Start preparing now&lt;/strong&gt; even if you're not migrating yet:

&lt;ul&gt;
&lt;li&gt;Adopt JSON source generation&lt;/li&gt;
&lt;li&gt;Use constructor injection&lt;/li&gt;
&lt;li&gt;Avoid reflection where possible&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;
&lt;h2&gt;
  
  
  The Future is AOT
&lt;/h2&gt;

&lt;p&gt;.NET's investment in NativeAOT is clear:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;.NET 8:&lt;/strong&gt; Stable for console apps, minimal APIs&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.NET 9:&lt;/strong&gt; Improved trimming, best warm performance (14ms avg)&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;.NET 10:&lt;/strong&gt; Smallest binaries (5.56 MB), fastest cold start (940ms)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each version shows &lt;strong&gt;measurable improvements&lt;/strong&gt; in size and performance.&lt;/p&gt;
&lt;h2&gt;
  
  
  Performance Variance Note
&lt;/h2&gt;

&lt;p&gt;⚠️ &lt;strong&gt;Important:&lt;/strong&gt; Your results may vary based on:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS region and AZ&lt;/li&gt;
&lt;li&gt;Time of day&lt;/li&gt;
&lt;li&gt;Lambda execution environment reuse&lt;/li&gt;
&lt;li&gt;Your specific workload&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The results shown represent &lt;strong&gt;averaged measurements from multiple test runs&lt;/strong&gt;. Individual runs may vary by ±5-15%.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Always benchmark your specific workload!&lt;/strong&gt;&lt;/p&gt;
&lt;h2&gt;
  
  
  Try It Yourself
&lt;/h2&gt;

&lt;p&gt;The complete source code, benchmarks, and detailed documentation are available:&lt;/p&gt;


&lt;div class="ltag-github-readme-tag"&gt;
  &lt;div class="readme-overview"&gt;
    &lt;h2&gt;
      &lt;img src="https://assets.dev.to/assets/github-logo-5a155e1f9a670af7944dd5e12375bc76ed542ea80224905ecaf878b9157cdefc.svg" alt="GitHub logo"&gt;
      &lt;a href="https://github.com/whitewAw" rel="noopener noreferrer"&gt;
        whitewAw
      &lt;/a&gt; / &lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison" rel="noopener noreferrer"&gt;
        dotnet-lambda-aot-performance-comparison
      &lt;/a&gt;
    &lt;/h2&gt;
    &lt;h3&gt;
      
    &lt;/h3&gt;
  &lt;/div&gt;
  &lt;div class="ltag-github-body"&gt;
    
&lt;div id="readme" class="md"&gt;&lt;div class="markdown-heading"&gt;
&lt;h1 class="heading-element"&gt;.NET NativeAOT: Performance Revolution&lt;/h1&gt;
&lt;/div&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;A Deep Dive into AOT vs ReadyToRun vs Regular .NET&lt;/h2&gt;
&lt;/div&gt;

&lt;p&gt;&lt;a href="https://github.com/vshymanskyy/StandWithUkraine/blob/main/docs/README.md" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/70ac67dd5447f117d2b4ca6315c2ece13631baf8208eb7f92eb49de6c3589393/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f5374616e645f576974682d556b7261696e652d4646443530303f6c6162656c436f6c6f723d303035424242" alt="Stand With Ukraine"&gt;&lt;/a&gt;
&lt;a href="https://github.com/whitewAw" rel="noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/8d3e9c6de645ce42c7682244312136e24f71b5691e1726819732762d4b919dba/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f446576656c6f7065645f62792d416c65785f2532384f6c656b73616e64722532395f536865766368656e6b6f2d3030363643433f6c6f676f3d676974687562" alt="Developed by"&gt;&lt;/a&gt;
&lt;a href="https://whitewaw.github.io/dotnet-lambda-aot-performance-comparison/performance-charts.html" rel="nofollow noopener noreferrer"&gt;&lt;img src="https://camo.githubusercontent.com/a8375c9d5a5ff77d3b61af0130d1849a961a0c6c66340bcf9d70293d81a81309/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4769744875625f50616765732d4c6976655f44656d6f2d3030643466663f6c6f676f3d676974687562" alt="GitHub Pages"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎬 Interactive Presentation&lt;/h2&gt;
&lt;/div&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;📊 &lt;a href="https://whitewaw.github.io/dotnet-lambda-aot-performance-comparison/NativeAOT-Presentation.html" rel="nofollow noopener noreferrer"&gt;Interactive Slide Presentation&lt;/a&gt;&lt;/strong&gt; - Full visual presentation with charts, comparisons, and code examples.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;📈 &lt;a href="https://whitewaw.github.io/dotnet-lambda-aot-performance-comparison/performance-charts.html" rel="nofollow noopener noreferrer"&gt;Performance Charts&lt;/a&gt;&lt;/strong&gt; - Interactive charts showing all benchmark results.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;📋 Table of Contents&lt;/h2&gt;

&lt;/div&gt;
&lt;ol&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#introduction--objectives" rel="noopener noreferrer"&gt;Introduction &amp;amp; Objectives&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#understanding-the-execution-models" rel="noopener noreferrer"&gt;Understanding the Execution Models&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#why-nativeaot-matters" rel="noopener noreferrer"&gt;Why NativeAOT Matters&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#performance-results-the-numbers-dont-lie" rel="noopener noreferrer"&gt;Performance Results: The Numbers Don't Lie&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#build--packaging-deep-dive" rel="noopener noreferrer"&gt;Build &amp;amp; Packaging Deep Dive&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#coding-for-aot-patterns--best-practices" rel="noopener noreferrer"&gt;Coding for AOT: Patterns &amp;amp; Best Practices&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#real-world-examples-from-this-repo" rel="noopener noreferrer"&gt;Real-World Examples from This Repo&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#deployment-strategies" rel="noopener noreferrer"&gt;Deployment Strategies&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#migration-guide" rel="noopener noreferrer"&gt;Migration Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#when-to-choose-which-approach" rel="noopener noreferrer"&gt;When to Choose Which Approach&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#faq--troubleshooting" rel="noopener noreferrer"&gt;FAQ &amp;amp; Troubleshooting&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#key-takeaways" rel="noopener noreferrer"&gt;Key Takeaways&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#additional-resources" rel="noopener noreferrer"&gt;Additional Resources&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#getting-started" rel="noopener noreferrer"&gt;Getting Started&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#contributing" rel="noopener noreferrer"&gt;Contributing&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#license" rel="noopener noreferrer"&gt;License&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison#acknowledgments" rel="noopener noreferrer"&gt;Acknowledgments&lt;/a&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="markdown-heading"&gt;
&lt;h2 class="heading-element"&gt;🎯 Introduction &amp;amp; Objectives&lt;/h2&gt;

&lt;/div&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;Who This Presentation Is For&lt;/h3&gt;

&lt;/div&gt;
&lt;p&gt;.NET engineers familiar with Lambda, microservices, or performance-critical applications looking to understand modern compilation strategies.&lt;/p&gt;
&lt;div class="markdown-heading"&gt;
&lt;h3 class="heading-element"&gt;What You'll Learn&lt;/h3&gt;

&lt;/div&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;NativeAOT fundamentals&lt;/strong&gt; and how it compares to ReadyToRun and Regular .NET&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Measured performance improvements&lt;/strong&gt; from real-world Lambda functions&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Practical build and deployment&lt;/strong&gt; strategies&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Code&lt;/strong&gt;…&lt;/li&gt;
&lt;/ul&gt;&lt;/div&gt;
  &lt;/div&gt;
  &lt;div class="gh-btn-container"&gt;&lt;a class="gh-btn" href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison" rel="noopener noreferrer"&gt;View on GitHub&lt;/a&gt;&lt;/div&gt;
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;What's included:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;✅ Working Lambda functions (.NET 8, 9, 10 AOT + R2R + Regular)&lt;/li&gt;
&lt;li&gt;✅ Containerized build pipeline&lt;/li&gt;
&lt;li&gt;✅ Performance testing invoker&lt;/li&gt;
&lt;li&gt;✅ CloudFormation templates&lt;/li&gt;
&lt;li&gt;✅ Detailed migration guide&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Discussion
&lt;/h2&gt;

&lt;p&gt;Have you tried NativeAOT on Lambda? What were your results? Drop a comment below!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Questions I'd love to hear:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;What's holding you back from trying AOT?&lt;/li&gt;
&lt;li&gt;What performance improvements have you seen?&lt;/li&gt;
&lt;li&gt;What challenges did you face during migration?&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;em&gt;If this helped you, consider ⭐ starring the repo and following me for more .NET performance deep-dives!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Connect:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub: &lt;a href="https://github.com/whitewAw" rel="noopener noreferrer"&gt;@whitewAw&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Repository: &lt;a href="https://github.com/whitewAw/dotnet-lambda-aot-performance-comparison" rel="noopener noreferrer"&gt;dotnet-lambda-aot-performance-comparison&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;




&lt;p&gt;&lt;strong&gt;Related Resources:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/core/deploying/native-aot/" rel="noopener noreferrer"&gt;Microsoft: Native AOT Deployment&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.aws.amazon.com/lambda/latest/dg/runtimes-custom.html" rel="noopener noreferrer"&gt;AWS: Lambda Custom Runtimes&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/source-generation" rel="noopener noreferrer"&gt;System.Text.Json Source Generation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  dotnet #aws #lambda #serverless #performance #nativeaot #csharp #cloudcomputing
&lt;/h1&gt;

</description>
      <category>dotnet</category>
      <category>aws</category>
      <category>serverless</category>
      <category>performance</category>
    </item>
    <item>
      <title>Building a Privacy-First Financial Analysis PWA with Blazor WebAssembly + On-Device AI (Gemini Nano)</title>
      <dc:creator>Oleksandr Shevchenko</dc:creator>
      <pubDate>Tue, 18 Nov 2025 21:14:38 +0000</pubDate>
      <link>https://dev.to/whitewaw/building-a-privacy-first-financial-analysis-pwa-with-blazor-webassembly-on-device-ai-gemini-nano-94a</link>
      <guid>https://dev.to/whitewaw/building-a-privacy-first-financial-analysis-pwa-with-blazor-webassembly-on-device-ai-gemini-nano-94a</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;Free, offline-capable, multi-language financial statement analysis for Ukrainian businesses - powered 100% in the browser (no servers, no API keys).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Live Demo: &lt;a href="https://whitewaw.github.io/Assessment-of-Ukrainian-financial-statements/" rel="noopener noreferrer"&gt;https://whitewaw.github.io/Assessment-of-Ukrainian-financial-statements/&lt;/a&gt;&lt;br&gt;&lt;br&gt;
GitHub Repo: &lt;a href="https://github.com/whitewAw/Assessment-of-Ukrainian-financial-statements" rel="noopener noreferrer"&gt;https://github.com/whitewAw/Assessment-of-Ukrainian-financial-statements&lt;/a&gt;&lt;/p&gt;


&lt;h2&gt;
  
  
  Why I Built This
&lt;/h2&gt;

&lt;p&gt;Small and medium businesses in Ukraine (and anywhere) often need quick insights from their balance sheet and income statement without sending data to third-party services or paying SaaS fees. I wanted:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Zero back-end infrastructure&lt;/li&gt;
&lt;li&gt;Professional-grade ratio analysis and multi-year comparison&lt;/li&gt;
&lt;li&gt;Installable PWA with offline mode&lt;/li&gt;
&lt;li&gt;Strict privacy: data never leaves the browser&lt;/li&gt;
&lt;li&gt;AI assistance without OpenAI keys or billing surprises&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Blazor WebAssembly + Chrome's built-in Gemini Nano made this possible.&lt;/p&gt;


&lt;h2&gt;
  
  
  Core Highlights
&lt;/h2&gt;

&lt;p&gt;Feature -&amp;gt; Benefit&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Blazor WebAssembly (.NET 10) -&amp;gt; Full C# front-end, no server required &lt;/li&gt;
&lt;li&gt;AOT Compilation -&amp;gt; Faster startup + optimized runtime&lt;/li&gt;
&lt;li&gt;On-Device AI (Gemini Nano) -&amp;gt; Private financial chat &amp;amp; contextual insights&lt;/li&gt;
&lt;li&gt;16 Analysis Tables -&amp;gt; Comprehensive coverage of capital, liquidity, solvency, efficiency &lt;/li&gt;
&lt;li&gt;7 Interactive Charts -&amp;gt; Visual composition &amp;amp; trend exploration &lt;/li&gt;
&lt;li&gt;Multi-Language (6) -&amp;gt; Ukrainian, English, German, Spanish, French, Russian&lt;/li&gt;
&lt;li&gt;PWA + Offline -&amp;gt; Works after first load; installable&lt;/li&gt;
&lt;li&gt;Local Storage + JSON Import/Export -&amp;gt; Data portability without backend&lt;/li&gt;
&lt;li&gt;Privacy-First -&amp;gt; No telemetry, no tracking, no API keys&lt;/li&gt;
&lt;/ul&gt;


&lt;h2&gt;
  
  
  AI Assistant: 100% Client-Side
&lt;/h2&gt;

&lt;p&gt;Chrome 127+ exposes a Prompt API enabling local inference via Gemini Nano. No keys, no cloud calls.&lt;/p&gt;

&lt;p&gt;Example capability prompt:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;capabilities&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nx"&gt;LanguageModel&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;availability&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;available&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sample financial question internally passed to the AI service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="kt"&gt;var&lt;/span&gt; &lt;span class="n"&gt;prompt&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="err"&gt;$&lt;/span&gt;&lt;span class="s"&gt;$"""
&lt;/span&gt;&lt;span class="n"&gt;Using&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;company&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="n"&gt;working&lt;/span&gt; &lt;span class="nf"&gt;capital&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WorkingCapitalCurrent&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="nf"&gt;ratio&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;CurrentRatio&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;debt&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="n"&gt;to&lt;/span&gt;&lt;span class="p"&gt;-&lt;/span&gt;&lt;span class="nf"&gt;equity&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;DebtToEquity&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;provide&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;A&lt;/span&gt; &lt;span class="n"&gt;concise&lt;/span&gt; &lt;span class="n"&gt;stability&lt;/span&gt; &lt;span class="n"&gt;assessment&lt;/span&gt;
&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Top&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt; &lt;span class="nf"&gt;risks&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;Recommended&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt; &lt;span class="n"&gt;action&lt;/span&gt;
&lt;span class="n"&gt;Answer&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;Ukrainian&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;source&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="n"&gt;locale&lt;/span&gt; &lt;span class="k"&gt;is&lt;/span&gt; &lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;uk&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
&lt;span class="s"&gt;"""$$;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The assistant streams responses for better UX and can explain formulas contextually.&lt;/p&gt;




&lt;h2&gt;
  
  
  Architecture Overview
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AFS/ (Blazor WASM App)
  App.razor          → Root + Router
  Pages/             → UI pages (AI Assistant, Tables, Charts)
  wwwroot/index.html → SEO meta + PWA shell
AFS.ComponentLibrary/
  Components/        → Reusable UI (Tables, Charts, Chat)
AFS.Core/
  Models/            → Financial &amp;amp; ratio models
  Services/          → Calculation + AI integration + Storage
  Interfaces/        → Abstractions (IAIFinancialAdvisor, etc.)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Key separation: &lt;code&gt;AFS.Core&lt;/code&gt; handles pure calculations (testable logic), while UI stays thin.&lt;/p&gt;




&lt;h2&gt;
  
  
  Financial Analysis Coverage
&lt;/h2&gt;

&lt;p&gt;Includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Liquidity: Current, Quick, Cash, Working Capital&lt;/li&gt;
&lt;li&gt;Solvency: Debt-to-Equity, Interest Coverage, Leverage&lt;/li&gt;
&lt;li&gt;Profitability: ROA, ROE, Margins&lt;/li&gt;
&lt;li&gt;Efficiency: Turnover metrics (assets, receivables, inventory, payables)&lt;/li&gt;
&lt;li&gt;Stability: Autonomy coefficient, classification levels&lt;/li&gt;
&lt;li&gt;Fixed &amp;amp; Intangible asset efficiency&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each table is generated from strongly typed models instead of ad-hoc dictionaries, enabling safer refactors.&lt;/p&gt;




&lt;h2&gt;
  
  
  Performance Choices
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;AOT publish shrinks cold start and improves runtime math-heavy loops&lt;/li&gt;
&lt;li&gt;IL trimming + Brotli compression reduces payload&lt;/li&gt;
&lt;li&gt;Critical CSS inlined in &lt;code&gt;index.html&lt;/code&gt; for faster LCP&lt;/li&gt;
&lt;li&gt;Service Worker caches static assets → instant repeat visits&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Publishing command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Release build with AOT&lt;/span&gt;
 dotnet publish AFS/AFS.csproj &lt;span class="nt"&gt;-c&lt;/span&gt; Release &lt;span class="nt"&gt;-o&lt;/span&gt; build
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Privacy &amp;amp; Data Handling
&lt;/h2&gt;

&lt;p&gt;No calls are made to external APIs for analysis. Data stays:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;In memory (runtime calculations)&lt;/li&gt;
&lt;li&gt;In browser Local Storage (optional save)&lt;/li&gt;
&lt;li&gt;Optional JSON export:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Year"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;2024&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Form1"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"AssetsTotal"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1234567&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Form2"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nl"&gt;"NetProfit"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;45678&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You control export/import - nothing is uploaded.&lt;/p&gt;




&lt;h2&gt;
  
  
  Getting Started (Local)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Clone&lt;/span&gt;
 git clone https://github.com/whitewAw/Assessment-of-Ukrainian-financial-statements.git
 &lt;span class="nb"&gt;cd &lt;/span&gt;Assessment-of-Ukrainian-financial-statements

&lt;span class="c"&gt;# Restore&lt;/span&gt;
 dotnet restore

&lt;span class="c"&gt;# Ensure WASM tooling&lt;/span&gt;
 dotnet workload &lt;span class="nb"&gt;install &lt;/span&gt;wasm-tools

&lt;span class="c"&gt;# Run&lt;/span&gt;
 dotnet run &lt;span class="nt"&gt;--project&lt;/span&gt; AFS
&lt;span class="c"&gt;# Visit https://localhost:7157&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Enable AI (Chrome):&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Update to Chrome 127+&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;chrome://flags/#prompt-api-for-gemini-nano&lt;/code&gt; → Enabled&lt;/li&gt;
&lt;li&gt;First run downloads Gemini Nano (~1.7GB one-time)&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  Example: Ratio Calculation Service (Simplified)
&lt;/h2&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight csharp"&gt;&lt;code&gt;&lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="k"&gt;class&lt;/span&gt; &lt;span class="nc"&gt;LiquidityRatioService&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;CurrentRatio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;currentAssets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;currentLiabilities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;currentLiabilities&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;currentAssets&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;currentLiabilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="nf"&gt;QuickRatio&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;liquidAssets&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;decimal&lt;/span&gt; &lt;span class="n"&gt;currentLiabilities&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;currentLiabilities&lt;/span&gt; &lt;span class="p"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;liquidAssets&lt;/span&gt; &lt;span class="p"&gt;/&lt;/span&gt; &lt;span class="n"&gt;currentLiabilities&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Integrated into a composite financial model so derived ratios are accessible to the AI advisor.&lt;/p&gt;




&lt;h2&gt;
  
  
  Internationalization (i18n)
&lt;/h2&gt;

&lt;p&gt;Resx-based resources under &lt;code&gt;AFS.ComponentLibrary/Resources/&lt;/code&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Resource.uk.resx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Resource.en.resx&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Culture selector updates displayed language instantly - no reload.&lt;/p&gt;




&lt;h2&gt;
  
  
  SEO &amp;amp; GitHub Pages Quirk
&lt;/h2&gt;

&lt;p&gt;Because this is a Blazor SPA hosted on GitHub Pages, Google Search Console may show a "False 404" during inspection of dynamic routes. A &lt;code&gt;404.html&lt;/code&gt; fallback mirrors &lt;code&gt;index.html&lt;/code&gt; so all routes hydrate properly. Canonical + hreflang tags are manually set in &lt;code&gt;index.html&lt;/code&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Roadmap (Selected)
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;PDF report generation (AI summary + graphs)&lt;/li&gt;
&lt;li&gt;Multi-company comparison panel&lt;/li&gt;
&lt;li&gt;Forecasting &amp;amp; anomaly detection (local AI augment)&lt;/li&gt;
&lt;li&gt;Optional cloud sync layer (opt-in)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Contributions welcome - especially localization or advanced financial models.&lt;/p&gt;




&lt;h2&gt;
  
  
  Lessons Learned
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;On-device AI drastically lowers friction (no keys, instant trust)&lt;/li&gt;
&lt;li&gt;Blazor AOT is now fast enough for real-time ratio computation&lt;/li&gt;
&lt;li&gt;Strong typing across financial models prevents subtle column mapping errors&lt;/li&gt;
&lt;li&gt;PWA + offline + privacy is a compelling trio for sensitive domains (finance, health, legal)&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How You Can Help
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;⭐ Star the repo if you find it useful&lt;/li&gt;
&lt;li&gt;🐛 Open issues for incorrect ratio definitions or edge cases&lt;/li&gt;
&lt;li&gt;🌍 Add new language translations&lt;/li&gt;
&lt;li&gt;📊 Contribute advanced metrics or sector benchmarks&lt;/li&gt;
&lt;li&gt;🤖 Improve AI prompts for financial diagnostics&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  Final Thoughts
&lt;/h2&gt;

&lt;p&gt;This project shows what’s now possible entirely in the browser: serious domain analysis + AI guidance without surrendering data or paying API bills. If you’re building privacy-first analytical tools, combining Blazor WebAssembly with on-device AI is absolutely worth exploring.&lt;/p&gt;

&lt;p&gt;Explore the demo, inspect the code, and feel free to fork.&lt;/p&gt;

&lt;p&gt;👉 Demo: &lt;a href="https://whitewaw.github.io/Assessment-of-Ukrainian-financial-statements/" rel="noopener noreferrer"&gt;https://whitewaw.github.io/Assessment-of-Ukrainian-financial-statements/&lt;/a&gt;&lt;br&gt;&lt;br&gt;
👉 Code: &lt;a href="https://github.com/whitewAw/Assessment-of-Ukrainian-financial-statements" rel="noopener noreferrer"&gt;https://github.com/whitewAw/Assessment-of-Ukrainian-financial-statements&lt;/a&gt;&lt;/p&gt;




&lt;h3&gt;
  
  
  Questions?
&lt;/h3&gt;

&lt;p&gt;Drop them in the comments or open a GitHub Discussion.&lt;/p&gt;

&lt;p&gt;Made with ❤️ + .NET + WebAssembly + On-Device AI.&lt;/p&gt;

</description>
      <category>blazor</category>
      <category>dotnet</category>
      <category>webassembly</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
