AutoMapper vs Mapster vs Mapperly in .NET: Which Object Mapper Should Your Team Use in 2026?

Object mapping is one of those tasks that every .NET team deals with and few teams agree on. You have data coming in from a database, an external API, or a queue, and you need to transform it into a DTO, a domain model, or a view model. The code to do this is rarely glamorous β but the library you choose to handle it shapes your team's debugging experience, your application's startup time, your hot-path performance, and your ability to catch mapping errors before they reach production. In 2026, the three main contenders β AutoMapper, Mapster, and Mapperly β have each matured in notably different directions, and the right choice depends on your team's constraints far more than any benchmark chart.
π Want implementation-ready .NET source code you can drop straight into your project? Join Coding Droplets on Patreon for exclusive tutorials, premium code samples, and early access to new content. π https://www.patreon.com/CodingDroplets
What Problem Does Object Mapping Solve β and Why Does Library Choice Matter?
Object mapping transforms one type into another. In layered ASP.NET Core applications, that means mapping Entity β DTO, Command β Domain Model, ExternalApiResponse β Internal Model, and back again. Done manually, this is boilerplate-heavy and error-prone. Done with a library, it is fast to write but slow to debug when something goes wrong silently.
The stakes get higher in enterprise systems where mapping logic runs on every API request, involves complex nested graphs, interacts with EF Core queries, and must be testable and traceable across dozens of profile configurations.
AutoMapper: The Veteran with Mature Ecosystem Support
AutoMapper has been the de facto standard for .NET object mapping for over a decade. It uses runtime reflection and expression trees to resolve mappings registered through Profile classes. The DI integration via IMapper is well understood, extensively documented, and compatible with every IoC container. Teams migrating legacy codebases or onboarding junior developers will find AutoMapper's learning curve the most forgiving.
Where AutoMapper genuinely excels:
- EF Core
ProjectTo<T>: AutoMapper's LINQ projection translates mapping configuration into SQL-level column selection through EF Core's expression tree pipeline. This avoids over-fetching data at the database level β a feature neither Mapster's default mode nor Mapperly provides out of the box. - Profile-based organisation: For large teams managing hundreds of mappings,
Profileclasses provide a structured, file-based convention that maps well to bounded contexts. - Community surface area: Stack Overflow, GitHub issues, and third-party integration packages all skew heavily toward AutoMapper.
Where AutoMapper hurts:
- Runtime exceptions: Mapping errors surface at runtime, not compile time. A misconfigured profile or a missing member silently passes unless
AssertConfigurationIsValid()is called in tests. - Startup cost: AutoMapper scans assemblies and builds expression trees at application startup. In large solutions with 50+ profiles, this adds measurable cold-start time β a concern for containerised microservices with aggressive readiness probe deadlines.
- Convention magic: AutoMapper's convention-based flattening is powerful but opaque. When a mapping behaves unexpectedly, tracing the resolution path requires knowing the library internals deeply.
Mapster: The Performance-Focused AutoMapper Challenger
Mapster was built with performance as a first principle. It uses expression tree compilation at startup to generate fast delegates, and its optional source-generator mode (Mapster.Tool) shifts that compilation entirely to build time for zero startup overhead. Mapster's API surface is intentionally familiar to AutoMapper users, making migration tractable β it even ships a compatible IMapper interface abstraction.
Where Mapster has a clear edge:
- Throughput on hot paths: Mapster's compiled delegates are measurably faster than AutoMapper's reflection-heavy resolution for high-volume scenarios. At 100,000+ mappings per second in low-latency APIs, the difference matters.
- Adaptive API: Mapster supports both fluent configuration and attribute-based configuration, and its
TypeAdapterConfigcan be scoped to avoid global state pollution in multi-tenant scenarios. - Source generator opt-in:
Mapster.Toolcan generate plain C# code at build time, giving you auditable, inspectable mapping code without sacrificing the convenience of configuration-driven mapping.
Where Mapster has gaps:
- EF Core
ProjectToequivalent: Mapster does not have a native LINQ projection equivalent to AutoMapper'sProjectTo. Teams relying on EF Core query projection for read models will need to handle this separately or keep AutoMapper alongside Mapster for data access. - Documentation depth: While Mapster's documentation has improved significantly, it still lacks the tutorial depth and community Q&A coverage that AutoMapper benefits from.
- Type safety at compile time: In its default (non-source-generator) mode, Mapster is still runtime-mapped. Only the
Mapster.Toolmode provides true compile-time guarantees.
Mapperly: Source Generators as the Foundation, Not a Feature
Mapperly takes the most opinionated approach of the three. It is a Roslyn source generator β there is no runtime mapping, no expression trees, no assembly scanning. Every mapping method you declare as partial in a [Mapper]-decorated class gets a full C# implementation generated at compile time. The generated code is readable, debuggable, and appears in your project's generated files.
Where Mapperly wins decisively:
- Compile-time correctness: Mapperly fails the build if a mapping is incomplete or ambiguous. There is no path to a runtime
AutoMapperMappingException. For teams with strong CI/CD pipelines, this is a significant reliability improvement. - Zero runtime overhead: Because all mapping code exists as plain C# before the application runs, Mapperly adds nothing to startup time or hot-path latency beyond the equivalent of hand-written code.
- AOT and trimming compatibility: Native AOT compilation and assembly trimming are production realities in .NET 8 and beyond. Mapperly is fully compatible. AutoMapper and Mapster's reflection-based defaults are not.
- Debuggable generated code: You can step through Mapperly-generated code in a debugger exactly like your own code. When a mapping goes wrong, you read the generated C# β not a stack trace through expression trees.
Where Mapperly has trade-offs:
- DI friction: Mapperly mappers are partial classes, not interfaces. They do not implement
IMapper, and they are not registered in the DI container by default. Wrapping them for DI injection requires an explicit pattern. - EF Core projection: Like Mapster, Mapperly has no built-in LINQ projection for EF Core. If query-level projection is part of your data access design, Mapperly alone does not cover that requirement.
- Migration effort from AutoMapper: Because the API surface is completely different, migrating an existing AutoMapper-heavy codebase to Mapperly is a significant refactor β one that must be weighed against the benefits.
Side-by-Side Comparison
| Dimension | AutoMapper | Mapster | Mapperly |
| Mapping approach | Runtime reflection + expression trees | Compiled delegates (or build-time via Mapster.Tool) | Roslyn source generator (always compile-time) |
| Compile-time safety | β No | β οΈ Partial (with Mapster.Tool) | β Yes |
| EF Core ProjectTo | β Native support | β Not supported | β Not supported |
| Startup overhead | MediumβHigh (profile scanning) | LowβMedium (default); None (Mapster.Tool) | None |
| Hot-path performance | Moderate | High | Highest (generated code) |
| Native AOT compatible | β No | β οΈ Partial | β Yes |
| DI integration | First-class IMapper | IMapper-compatible adapter | Manual wrappers required |
| Learning curve | Low (mature docs, large community) | LowβMedium | Medium (source gen mental model) |
| Debuggability | Hard (expression trees) | Moderate | Easy (generated C# is browsable) |
| Migration from AutoMapper | N/A | Low effort (familiar API) | High effort (full rewrite) |
π» Run the Benchmarks Yourself
Want to see the actual numbers on your machine? The full benchmark project is available on GitHub.
π dotnet-object-mapper-benchmark on GitHub
Clone it, run dotnet run -c Release, and see exactly how AutoMapper, Mapster, and Mapperly perform in your environment.
When to Use Each
Use AutoMapper when:
You have a large existing ASP.NET Core application that already uses AutoMapper profiles, your team relies on EF Core ProjectTo for read-heavy query optimisation, and you have no immediate Native AOT requirements. The cost of migration exceeds the benefit of switching, particularly when the application is in maintenance mode.
Use Mapster when:
You are building or refactoring a high-throughput API where mapping performance matters, but you need to retain EF Core query projection or migrate incrementally from AutoMapper. Mapster's IMapper-compatible adapter makes side-by-side migration achievable profile by profile. If you enable Mapster.Tool, you also gain compile-time safety at the profile level without abandoning your existing patterns.
Use Mapperly when:
You are starting a greenfield ASP.NET Core service, building a microservice that targets Native AOT, or writing a service where mapping correctness at build time is non-negotiable. Mapperly's compile-time guarantees fit naturally into DDD-style applications where explicit, auditable transformations are architecturally preferred over convention-based magic.
The EF Core ProjectTo Decision
This is the most frequently overlooked trade-off. AutoMapper's ProjectTo<T> participates in IQueryable expression trees, meaning EF Core only fetches the columns your DTO actually needs. For read-heavy APIs serving large datasets, this is not a performance nicety β it is a database load management requirement.
Neither Mapster (in default mode) nor Mapperly offers an equivalent. Teams adopting Mapster or Mapperly for mapping but still relying on EF Core projection typically isolate their data access layer to manual Select() LINQ projections or use AutoMapper solely for the ProjectTo use case while delegating in-memory transformations to Mapster or Mapperly. This hybrid approach is architecturally valid but requires explicit convention documentation to prevent team confusion.
Is Manual Mapping Worth Revisiting?
The debate around "just write it by hand" resurfaces in every .NET community discussion on this topic. For teams using Mapperly, hand-written mapping and Mapperly-generated mapping are nearly equivalent in what you read and debug β the difference is that Mapperly generates and maintains the boilerplate automatically. For teams using AutoMapper or Mapster, the configuration-driven model saves repetitive code but introduces a layer of indirection that hand-written mapping avoids.
If your service has fewer than 10 DTO types, manual mapping is a legitimate choice. For enterprise-scale solutions with 50+ entity types, bounded context DTOs, and frequent schema evolution, a library that enforces consistency pays for itself in reduced review overhead alone.
Migration Path: Moving Away from AutoMapper
If you are on AutoMapper and considering a move, the recommended path is:
- Audit
ProjectTousage first. If it is pervasive, factor EF Core projection handling into your decision before committing to either Mapster or Mapperly. - Mapster as a drop-in path: Install Mapster, register it with the
IMapper-compatible adapter, and migrate profiles bounded context by bounded context. Run both libraries in parallel during the transition. - Mapperly as a clean-slate path: Reserve Mapperly migration for services being refactored or rewritten. Do not attempt to migrate a large existing codebase to Mapperly profile-by-profile β the pattern mismatch makes it slower than a targeted rewrite.
β Prefer a one-time tip? Buy us a coffee β every bit helps keep the content coming!
Frequently Asked Questions
Is AutoMapper still actively maintained in 2026?
Yes. AutoMapper continues to receive updates, though the community conversation has shifted toward alternatives like Mapster and Mapperly for performance-sensitive and AOT-targeting scenarios. It remains the safest choice for legacy migration and EF Core ProjectTo use cases.
Can I use both AutoMapper and Mapperly in the same project?
Yes, and this pattern is used deliberately by teams that rely on AutoMapper exclusively for EF Core ProjectTo projection and route all other in-memory transformations through Mapperly. The cost is maintaining two mapping conventions, which should be documented explicitly.
Does Mapster work with Native AOT in .NET 9/10?
Mapster's default runtime mode does not support Native AOT due to its use of reflection and dynamic delegate generation. The Mapster.Tool source generator mode produces AOT-compatible output. If you target Native AOT, use Mapster.Tool or Mapperly exclusively.
How does Mapperly handle null propagation in nested mappings? Mapperly generates explicit null checks in its mapping methods based on nullability annotations on your types. If a property is nullable, the generated code handles it accordingly. This is in contrast to AutoMapper and Mapster, where null handling behaviour depends on runtime configuration.
What is the performance difference between AutoMapper and Mapster in a real-world API? Benchmarks consistently show Mapster's compiled delegate mode running 3-5Γ faster than AutoMapper for simple property-to-property mappings. For complex nested graphs, the gap narrows but Mapster still leads. Mapperly (source-generated) performs on par with hand-written code β effectively the upper bound for any mapping library.
Should new ASP.NET Core projects in 2026 still use AutoMapper?
For greenfield projects without EF Core ProjectTo requirements and targeting .NET 8 or later, AutoMapper is not the recommended starting point. Mapster (with Mapster.Tool) or Mapperly provides better performance, tighter compile-time guarantees, and a cleaner fit with the current .NET platform direction toward AOT-compatible, reflection-free code.
How do I register Mapperly mappers in ASP.NET Core DI?
Mapperly does not auto-register with the DI container. The recommended pattern is to declare your mapper as a partial class, wrap it in an interface, and register that interface manually in Program.cs. Some teams use a thin factory or extension method to centralise this registration per bounded context.






