Skip to content

Pinox/FastEndpointsAOT

Repository files navigation

FastEndpoints Native AOT

A fully functional Native AOT implementation of FastEndpoints for .NET 10. This repo exist as iteration playground until the official fastendpoint repo becomes fully AOT compatible.

This has been a "guided" vibe coded implementation so do take care in checking details. My main aim was just to get it working therefor trimming on many libs have been disabled in the rd.xml file. Further iteration is needed to improve the code for production.

🎯 Overview

This project demonstrates how to run FastEndpoints with Native AOT compilation, achieving:

  • Not using JIT compilation at runtime
  • 📦 Single-file deployment (~15MB self-contained executable)
  • 🚀 Reduced memory footprint
  • 🔒 Hopefully reduced cost for cloud service

📋 Prerequisites

🚀 Quick Start

# Navigate to the project root
cd FastEndpointsAOT-main

# Run in development mode (JIT)
cd Web
dotnet run

# Publish as Native AOT (from project root)
cd Web
dotnet publish -c Release -o ../publish

The published executable will be in ./publish/Web.exe.

📁 Project Structure

Folder Description
Web/ Main API application with FastEndpoints
Shared/ Shared DTOs, contracts, and HttpClient extensions
ApiRequestGenerator/ Source generator for AOT-compatible API request metadata
Tests/ Integration and unit tests
Benchmark/ Performance benchmarks using BenchmarkDotNet and Bombardier
Src/ FastEndpoints source (for reference/customization)

✨ Key Features

Source Generator for API Requests

The ApiRequestGenerator automatically scans your FastEndpoints and generates AOT-compatible metadata:

  • Extracts routes and HTTP methods from Configure() methods
  • Generates IApiRequest<TSelf, TResponse> implementations with static JSON type info
  • Enables clean HttpClient usage without reflection
// Auto-generated: each request DTO knows its route, method, and serialization
public partial class LoginRequest : IApiRequest<LoginRequest, LoginResponse>
{
    // Route extracted from endpoint's Configure() method
    static string Route => "/api/admin/login";
    
    // HTTP method (Post, Get, Put, Delete, Patch)
    static HttpMethod Method => HttpMethod.Post;
    
    // AOT-safe JSON serialization metadata
    static JsonTypeInfo<LoginRequest>  RequestTypeInfo  => SharedJsonContext.Default.LoginRequest;
    static JsonTypeInfo<LoginResponse> ResponseTypeInfo => SharedJsonContext.Default.LoginResponse;
}

AOT-Compatible HttpClient Extensions

Clean, type-safe API calls with automatic serialization:

// Request types know their own route, method, and serialization
var (response, result) = await client.SendAsync(new LoginRequest 
{ 
    Email = "user@example.com", 
    Password = "pass" 
});

// Response type is automatically inferred from IReturn<TResponse>
if (response.IsSuccessStatusCode)
{
    Console.WriteLine($"Token: {result.Token}");
}

Scalar API Explorer

Interactive API documentation available at localhost:5000/api in development mode.

Real-World Benchmarking

Update - This issue has been resolved. Steps just noted.

Why this is safe:

  1. The custom ResponseSerializer writes the actual response data first
  2. The exception occurs after the response is written, not during
  3. The buffer contains the complete, valid response
  4. Minimal performance overhead (exception filters have near-zero cost when no exception occurs)

See Web/Hostings/AotResponseBufferingMiddleware.cs for implementation details.

External AOT Tests

The ExternalAotTests require the published Native AOT app to be running on localhost:5000:

# Terminal 1: Start the published app
./publish/Web.exe

# Terminal 2: Run external AOT tests
dotnet test Tests\IntegrationTests\FastEndpoints

These tests validate the actual AOT-compiled binary against real HTTP requests.

📊 Benchmarks

cd Benchmark
./run-all-benchmarks.ps1

🔧 Configuration

Release Build (Native AOT)

The project is configured for Native AOT in Release mode:

<PropertyGroup Condition="'$(Configuration)' == 'Release'">
    <PublishAot>true</PublishAot>
    <SelfContained>true</SelfContained>
    <PublishTrimmed>true</PublishTrimmed>
    <StripSymbols>true</StripSymbols>
</PropertyGroup>

📚 Resources

📄 License

See LICENSE.md for details.

Scalar Ping-Pong

About

Iteration to get FastEndpoints working with AOT

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Sponsor this project

Packages

No packages published