Skip to content
quyvu edited this page Oct 15, 2026 · 4 revisions

Frequently Asked Questions

Short, direct answers about FxMap: what it is, how it compares with other tools, which transports and databases it supports, and how to get help.

GeneralGetting startedTransports and dataReliability and operationsCommunity and AI

General

FxMap is an open-source (Apache-2.0) .NET library for distributed data mapping between microservices. With a fluent API you declare which properties of a DTO should be filled from another service, for example UserName and UserEmail from a UserId. FxMap fetches them from the service that owns the data and writes them back. It targets .NET 8, 9 and 10.

In a microservice system a response often carries only keys: an order has a UserId, a ProvinceId, a ProductId. Showing it means collecting names and details from the services that own them, and writing that glue again for every endpoint. FxMap turns the glue into a declaration: a ProfileOf<T> on the consuming service and an EntityConfigureOf<T> on the owning service. FxMap batches the ids, sends them over a transport and fills the DTO.

Use FxMap when your responses reference entities that are owned by other services and you want to enrich them without writing a client call per field. You do not need it when all the data lives in one database, where a join or a projection is simpler.

AutoMapper copies values from one object to another inside a process. FxMap fills properties with data that lives in other services, across a transport such as gRPC or a message broker. They solve different problems and can be used together. In the repository's in-process benchmark (EF Core InMemory, no network) FxMap was on par with or faster than a single joined AutoMapper ProjectTo past a few dozen objects and allocated half to a third of the memory. With a real database or transport the network round trips dominate, so treat those numbers as a measure of mapper overhead only.

Yes. FxMap is released under the Apache License 2.0, which allows commercial use, modification and distribution as long as you keep the license and notices. This is general information, not legal advice; read the license text for the details.

Getting started

Add the core package to every service that maps data. The service that owns the data also needs a data provider, and both sides need the same transport. All FxMap.* packages must use the same version.

dotnet add package FxMap
dotnet add package FxMap.EntityFrameworkCore   # on the service that owns the data
dotnet add package FxMap.Grpc                  # or FxMap.Nats, FxMap.RabbitMq, FxMap.Kafka, ...

Declare a profile for the DTO, register it, then call IDistributedMapper.MapDataAsync. The owning service registers an EntityConfigureOf<T> for the entity. See Your first mapping for the full walkthrough.

public class OrderResponseProfile : ProfileOf<OrderResponse>
{
    protected override void Configure() =>
        UseDistributedKey<UserDistributedKey>()
            .Of(x => x.UserId)
            .For(x => x.UserName)
            .For(x => x.UserEmail, "UserEmail");
}
 
await distributedMapper.MapDataAsync(orderResponse);

It is MapDataAsync(object value, CancellationToken token = default) on IDistributedMapper. There is no MapAsync or MapManyAsync. It mutates the object, or the collection of objects, that you pass in and returns a Task.

FxMap targets .NET 8, .NET 9 and .NET 10.

A distributed key identifies an entity across services. The simplest option is a small shared contracts project with a sealed class implementing IDistributedKey. If services cannot share a type, use a string key on both sides: UseDistributedKey("UserDistributedKey"). The key is a name made of identifiers separated by dots, such as UserDistributedKey or MyApp.Keys.UserKey (letters, digits and underscores in each part). It must match exactly on both sides, and both sides must also use the same form, either a type or a string.

FxMap 5.0 removed the indexer (Orders[0 10 asc Date]) and the filter (Orders(Status = 'Done')) from the expression language. Use the functions :where, :orderBy, :offset, :limit, :first and :last instead, for example Orders:where(Status = 'Done'):orderBy(Date):first. FxMap.Analyzers 5.0 reports the old syntax as OFX001 when you build. An expression is parsed by the service that owns the data, so upgrade the owners and the consumers of those expressions in the same window. The upgrade guide has the full table of replacements: https://fxmapper.net/docs/migrate-to-v5/

FxMap 5.1 made the public API smaller. The configuration is published by interfaces, and the classes that implement them, with the expression engine, are internal. Code that names MapConfigurator, NatsClientSetting, KafkaConfigurator and similar types must use the interface instead (IMapConfigurator, INatsConfigurator, IKafkaConfigurator...). Code that only writes AddFxMap(cfg => ...) with a lambda is not affected. 5.1 also fixes the retry policy: the delay is waited before each retry, the last exception is thrown, and a local handler is no longer retried. See https://fxmapper.net/docs/migrate-to-v5-1/

Transports and data

gRPC, NATS, RabbitMQ, Apache Kafka, Azure Service Bus and Amazon SQS. Both sides of a mapping use the same transport. See Transports for setup of each one.

Entity Framework Core (SQL Server, PostgreSQL, MySQL, SQLite and any other EF Core provider) through FxMap.EntityFrameworkCore, and MongoDB through FxMap.MongoDb. The service that owns the data registers the provider; services that only consume data need none. See Data providers.

Yes. FxMap.HotChocolate fills GraphQL response types through HotChocolate, so the data is mapped before the response is serialized. See the HotChocolate integration.

The service that owns the data needs an HTTP/2 endpoint. Without TLS, use a dedicated HTTP/2-only endpoint next to your HTTP/1.1 one; with TLS a single Http1AndHttp2 endpoint works. See Kestrel (HTTP/2) for the appsettings.json sample.

FxMap batches lookups: one request per distributed key and dependency level, with distinct ids, however many objects you map. A hundred orders that all need a UserName produce one request for the users. Chains such as UserId to ProvinceId to CountryId resolve level by level.

Yes. .For(...) accepts an expression in FxMap's own expression language: navigation (Country.Name), filters (Orders:where(Status = 'Done')), aggregations (Orders:sum(Total)), projections ({Id, Name}), functions, coalesce, ternary and groupBy. Expressions are strings and are not C# or LINQ. See the expression language.

.For(x => x.TotalSpent, "Orders:where(Status = 'Done'):sum(Total)")

Reliability and operations

By default FxMap catches and swallows exceptions and leaves the properties at their default values. Call ThrowIfException() in AddFxMap to fail fast; it is a good idea in development. For transient failures configure SetRetryPolicy(...); the default request timeout is 30 seconds and can be changed with SetRequestTimeOut(...). Message-based transports also use a supervisor with backoff and a circuit breaker (enabled by default). See Error handling and Retry policy.

Yes. FxMap emits activities for OpenTelemetry tracing on mapping and data access. See Telemetry to wire it to your exporter.

Yes. The FxMap.Analyzers package is a Roslyn analyzer that reports misconfigured profiles and entities and validates expression strings while you compile. See Analyzers.

Community and AI

Join the Discord server, open a GitHub issue for a bug, or start a GitHub discussion for a question or an idea.

Yes, and it does better with the right context. The AI Skills page offers markdown files that teach assistants the real FxMap API, such as MapDataAsync and the registration order. A plain-text overview of the whole site is available at llms.txt.


Source: https://fxmapper.net/docs/faq/ — the website is always the most up to date version.

Clone this wiki locally