Skip to content

FxMap vs Alternatives

quyvu edited this page Oct 13, 2026 · 2 revisions

FxMap vs Alternatives

Several ways exist to put data owned by other services into a response. Here is how they differ, what each costs, and when FxMap is the right fit.

The Problem

In a microservice system a response often carries only keys: an order has a UserId and a ProductId. Showing it means collecting names and details from the services that own them, without a database join to lean on. Every approach below is an answer to that one problem.

Side by Side

Hand-written calls (HttpClient / gRPC clients)

Each endpoint calls the services that own the data and copies the values into the response.

Strengths

Fully explicit, no extra library, easy to debug.

Trade-offs

Repeated glue code in every endpoint; easy to introduce N+1 calls; every field is more code to maintain.

Choose it when

You have one or two enrichment points and a small team.

API gateway or BFF composition

A gateway or backend-for-frontend calls several services and assembles the response.

Strengths

Keeps composition out of the domain services and close to the client.

Trade-offs

The composition logic still has to be written and kept in sync; the gateway becomes a place that knows every service.

Choose it when

Composition belongs to one client experience and one team owns the gateway.

GraphQL federation

A federated graph resolves fields across services through a gateway.

Strengths

Clients choose the fields they need; strong tooling and schema contracts.

Trade-offs

Requires adopting GraphQL and a gateway or router; resolvers and entity references to maintain.

Choose it when

You already expose GraphQL, or want clients to shape their own queries.

Read models (CQRS projections, event-carried state)

Services publish events and consumers keep a local copy of the data they need.

Strengths

Reads are local and fast; a consumer keeps working when the owner is down.

Trade-offs

Eventual consistency, storage duplication, and the work of building and operating the projections.

Choose it when

You need low-latency reads or high availability and can accept stale data.

AutoMapper, Mapster, Mapperly

In-process object-to-object mapping.

Strengths

Excellent at what they do: copying and shaping data you already have.

Trade-offs

They do not fetch data from other services, so they solve a different problem.

Choose it when

Always, for in-process mapping. They combine well with FxMap.

FxMap

You declare which DTO properties come from which service; FxMap batches the ids, fetches the values over a transport and fills the DTO.

Strengths

Declarative, one request per key and level instead of one per object, compile-time analyzers, and it works across gRPC and message brokers. The owning service exposes entities through a configuration class rather than hand-written endpoints.

Trade-offs

Data is fetched at request time, so latency and availability depend on the owning service (retries and supervision help). Services share key names and need an entity config for each exposed entity.

Choose it when

Many endpoints return keys that need names and details from other services, and you want that as a declaration rather than glue code.

Approach Strengths Trade-offs Choose it when

| Hand-written calls (HttpClient / gRPC clients)

Each endpoint calls the services that own the data and copies the values into the response.

| Fully explicit, no extra library, easy to debug. | Repeated glue code in every endpoint; easy to introduce N+1 calls; every field is more code to maintain. | You have one or two enrichment points and a small team. | |

API gateway or BFF composition

A gateway or backend-for-frontend calls several services and assembles the response.

| Keeps composition out of the domain services and close to the client. | The composition logic still has to be written and kept in sync; the gateway becomes a place that knows every service. | Composition belongs to one client experience and one team owns the gateway. | |

GraphQL federation

A federated graph resolves fields across services through a gateway.

| Clients choose the fields they need; strong tooling and schema contracts. | Requires adopting GraphQL and a gateway or router; resolvers and entity references to maintain. | You already expose GraphQL, or want clients to shape their own queries. | |

Read models (CQRS projections, event-carried state)

Services publish events and consumers keep a local copy of the data they need.

| Reads are local and fast; a consumer keeps working when the owner is down. | Eventual consistency, storage duplication, and the work of building and operating the projections. | You need low-latency reads or high availability and can accept stale data. | |

AutoMapper, Mapster, Mapperly

In-process object-to-object mapping.

| Excellent at what they do: copying and shaping data you already have. | They do not fetch data from other services, so they solve a different problem. | Always, for in-process mapping. They combine well with FxMap. | |

FxMap

You declare which DTO properties come from which service; FxMap batches the ids, fetches the values over a transport and fills the DTO.

| Declarative, one request per key and level instead of one per object, compile-time analyzers, and it works across gRPC and message brokers. The owning service exposes entities through a configuration class rather than hand-written endpoints. | Data is fetched at request time, so latency and availability depend on the owning service (retries and supervision help). Services share key names and need an entity config for each exposed entity. | Many endpoints return keys that need names and details from other services, and you want that as a declaration rather than glue code. |

How to Decide

FxMap fits when

  • Many endpoints repeat the same lookups of names and details by key.
  • You use .NET and a transport you already run (gRPC, NATS, RabbitMQ, Kafka, Azure Service Bus, Amazon SQS).
  • You can accept request-time reads and want retries, supervision and tracing around them.

Look elsewhere when

  • All the data lives in one database: a join or a projection is simpler.
  • You need reads to survive the owning service being down: use read models.
  • Your clients already shape their own queries through GraphQL federation.

These approaches are not exclusive. FxMap also integrates with HotChocolate, so a GraphQL API can have its response types filled by FxMap.


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

Clone this wiki locally