Feature roadmap: Source generation, AOT/trimming, package size and serialization speed (generated mappers, AOT annotations, expression interpreter)
A recurring set of requests is about what LiteDB costs at runtime and at deploy time, not about new features: startup and serialization speed, compatibility with ahead-of-time compilation and trimming, and the size of the package. All of them come back to the same design point. BsonMapper discovers types with reflection and builds getters, setters and constructors by compiling expression trees at runtime, and the query layer compiles BsonExpressions the same way. That is flexible, but it costs time on first use, it breaks on AOT-only runtimes, and it makes the library hard to trim. The common ask is a compile-time path, generated mapping code, alongside the reflection-based one. This issue collects those requests.
Requests
- #1667 — opt-in Roslyn source generators for mapping and expression trees, keeping reflection as the fallback
- #2334 — use MessagePack or MemoryPack to speed up serialization and reduce RAM and disk use
- #1826 — split the SQL layer into a separate assembly (
LiteDB.dll+LiteDB.Sql.dll) to reduce size
Current state on dev
- Reflection and runtime compilation: the mapper builds constructors, getters and setters with
Expression.Lambda(...).Compile()(Reflection.Expression.cs#L20, #L42, #L80). LINQ translation evaluates captured values the same way (LinqExpressionVisitor.cs#L723), and everyBsonExpressionis compiled (BsonExpression.cs#L365). The repository has no source generator project. - AOT and trimming: the package targets
netstandard2.0andnet8.0(LiteDB.csproj#L4). It isn't marked trimmable or AOT-compatible and has no trimming annotations. On runtimes without dynamic code (iOS, Unity IL2CPP) the compiled expressions are the crash point tracked in #2804. Practical options today: on .NET 8+ NativeAOT,System.Linq.Expressionsfalls back to its interpreter, which is slower but works for many cases. When trimming, root your entity types (for example withDynamicDependencyor aTrimmerRootDescriptor) so the mapper still finds their members. - Serialization speed (#2334): the storage format is BSON and stays BSON. Queries, indexes,
BsonExpression, the shell and cross-version readability all rely on self-describing fields. MessagePack and MemoryPack are schema-less binary formats, so they can't be the document format of this database. What is possible is the part MemoryPack does well: generating the conversion code at compile time. Today the practical speed-up for hot types is a hand-writtenRegisterType<T>(serialize, deserialize)(BsonMapper.cs#L140), which skips reflection for that type. - Package size (#1826): the SQL command parser (Client/SqlParser/) is about 860 of roughly 38,000 lines of code in the library, around 2%. The expression engine it uses (Document/Expression/) is also required by indexes,
Queryand LINQ, so it can't move out of the core. A separateLiteDB.Sql.dllwould save only a few KB.
Possible direction
Small (v6 candidates):
- Add trimming and AOT annotations (
IsTrimmable,RequiresDynamicCode/RequiresUnreferencedCodeon the reflection entry points) so trim warnings point at the right APIs instead of failing at runtime. - Add a NativeAOT publish smoke test to CI that inserts, queries and reads back a POCO, so regressions are visible.
Larger (v6 candidates):
- Source-generated mappers (#1667, #2334): an incremental generator, triggered by a marker attribute on a partial class or an assembly-level list of types. It would emit plain-delegate
EntityMappers (constructor, getters, setters, member metadata) and register them inBsonMapperahead of the reflection path. Reflection stays as the fallback for dynamically loaded types, F# and older project styles. Snapshot tests of the generated code and round-trip tests comparing generated and reflection output would guard it. - Expression evaluation without runtime compilation: an interpreted path for
BsonExpressionand LINQ captured values. This is the other half of AOT support and overlaps with #2804. Generated mappers alone don't removeBsonExpressioncompilation.
Not planned:
- Replacing BSON with MessagePack or MemoryPack as the storage format (#2334).
- Splitting SQL into its own assembly (#1826). The size gain is too small for a second package that must be versioned in lockstep. Trimming support is the better way to shrink deployments.
Related issues
This consolidates the following requests, which are closed as duplicates of this issue:
- #1667 — opt-in source generators for mapping and expression trees
- #2334 — MessagePack/MemoryPack (or source-generated mapping) for faster serialization
- #1826 — separate SQL assembly to reduce package size
Also related (still open): #2894 (includes #2730: a trimmed build fails with NullReferenceException in GetTypeCtor instead of a clear error), #2804 (crashes on iOS and other AOT-only runtimes because expression trees are compiled at runtime), #2623 (v6 planning), #2830 (pluggable compression and hashing, the "smaller on disk" part of #2334).
Source: litedb-org/LiteDB