Skip to main content

AOT Compatibility

FluentDynamoDB is fully compatible with .NET Native AOT compilation.

What is Native AOT?

Native AOT compiles your application to native code ahead of time, resulting in:

  • Faster startup times
  • Lower memory usage
  • Smaller deployment size
  • No JIT compilation overhead

How FluentDynamoDB Achieves AOT Compatibility

  • Source generators eliminate runtime reflection
  • No dynamic code generation
  • All types known at compile time
  • Trimming-safe design

Configuration

Basic AOT Setup

For AOT compatibility, use source-generated JSON serialization with JsonSerializerContext:

using System.Text.Json.Serialization;
using Oproto.FluentDynamoDb;
using Oproto.FluentDynamoDb.SystemTextJson;

// 1. Define your JSON context with all types that need serialization
[JsonSerializable(typeof(DocumentContent))]
[JsonSerializable(typeof(List<string>))]
[JsonSerializable(typeof(Dictionary<string, object>))]
public partial class AppJsonContext : JsonSerializerContext
{
}

// 2. Configure FluentDynamoDbOptions with the context
var options = new FluentDynamoDbOptions()
.WithSystemTextJson(AppJsonContext.Default);

var table = new DocumentTable(dynamoDbClient, "documents", options);

Entity Definition for AOT

[DynamoDbTable("documents")]
public partial class Document
{
[PartitionKey]
[DynamoDbAttribute("pk")]
public string Pk { get; set; } = string.Empty;

[SortKey]
[DynamoDbAttribute("sk")]
public string Sk { get; set; } = string.Empty;

[DynamoDbAttribute("title")]
public string Title { get; set; } = string.Empty;

// JSON blob properties require JsonSerializerContext for AOT
[JsonBlob]
[DynamoDbAttribute("content")]
public DocumentContent Content { get; set; } = new();
}

public class DocumentContent
{
public string Body { get; set; } = string.Empty;
public List<string> Tags { get; set; } = new();
}

CRUD Operations

All standard operations work with AOT compilation:

// Create
var document = new Document
{
Pk = Document.Keys.Pk("doc123"),
Sk = Document.Keys.Sk(),
Title = "My Document",
Content = new DocumentContent
{
Body = "Document body",
Tags = new List<string> { "aot", "example" }
}
};

await table.Documents.PutAsync(document);

// Read
var retrieved = await table.Documents.GetAsync("doc123");

// Query
var results = await table.Documents.Query()
.Where(x => x.Title == "My Document")
.ToListAsync();

// Update
await table.Documents.Update("doc123")
.Set(x => new { Title = "Updated Title" })
.UpdateAsync();

// Delete
await table.Documents.DeleteAsync("doc123");

Publishing for AOT

dotnet publish -c Release -r linux-x64 -p:PublishAot=true

Project File Configuration

<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<PublishAot>true</PublishAot>
<TrimMode>full</TrimMode>
</PropertyGroup>
</Project>

Benefits for Serverless

Native AOT is ideal for AWS Lambda and other serverless environments where cold start time matters:

  • Cold start reduction: Up to 80% faster cold starts
  • Memory efficiency: Lower memory footprint
  • Consistent performance: No JIT warmup period

Lambda Example

public class Function
{
private readonly DocumentTable _table;

public Function()
{
var client = new AmazonDynamoDBClient();
var options = new FluentDynamoDbOptions()
.WithSystemTextJson(AppJsonContext.Default);

_table = new DocumentTable(client, "documents", options);
}

public async Task<Document?> FunctionHandler(string documentId, ILambdaContext context)
{
return await _table.Documents.GetAsync(documentId);
}
}

Troubleshooting

Missing Types in JsonSerializerContext

If you see serialization errors at runtime, ensure all types used in [JsonBlob] properties are registered:

// Register all types that appear in JSON blobs
[JsonSerializable(typeof(DocumentContent))]
[JsonSerializable(typeof(UserPreferences))]
[JsonSerializable(typeof(List<string>))]
[JsonSerializable(typeof(Dictionary<string, string>))]
public partial class AppJsonContext : JsonSerializerContext
{
}

Trimming Warnings

If you see trimming warnings during publish, ensure your entities are partial classes so the source generator can add the necessary code:

// Correct - partial class
[DynamoDbTable("documents")]
public partial class Document { }

// Incorrect - will cause trimming issues
[DynamoDbTable("documents")]
public class Document { }