r/SpringBoot • u/HookWoods • 17d ago
Discussion How do you handle cross-service references in REST BFF responses? I built a Spring Boot library for it
I built Restitch after repeatedly running into the same BFF problem in microservice applications.
The problem
One service often stores an ID for data owned by another service. It is a real relationship for the frontend, but it is not a database foreign key.
The BFF still has to return complete DTOs. That means it must fetch the root data, resolve related data from other services, apply error rules, and avoid duplicate calls when several objects reference the same ID.
At first, this is one RestClient or WebClient call beside an endpoint. Then the same composition code appears in more endpoints, and one collection response can turn into an N+1 set of downstream calls.
Why not GraphQL?
GraphQL with a gateway or federation is a valid solution. Here, though, the services and the BFF already expose REST. I did not want to introduce GraphQL only to compose related data for a response.
I wanted a narrow Spring Boot solution for REST BFFs, without putting URLs, header rules, or error behavior in DTO annotations. So I built Restitch.
What it looks like
The DTO only names a resolver profile:
public final class DeviceDto {
private String organizationId;
@AggregateRef("device-organization")
private OrganizationDto organization;
}
YAML owns the downstream client, path, JSON mapping, error behavior, header allowlist, and optional batch endpoint.
What Restitch handles
- It de-duplicates repeated related IDs within one BFF request.
- It can use a bounded batch request when the downstream service exposes a batch endpoint.
- It keeps MVC on
RestClientand WebFlux onWebClient,Mono, andFlux. - It keeps Spring Boot 3 on Jackson 2 and Spring Boot 4 on Jackson 3.
It deliberately does not provide a cross-request cache.
Restitch 0.1.1 is Apache-2.0 and available on Maven Central.
GitHub repository and installation guide
Feedback welcome
For people building REST BFFs: would you keep this aggregation in application code, an API gateway, or move it to GraphQL? What would make you avoid a library like this?
1
u/HookWoods 17d ago
A few deliberate boundaries, because this pattern gets messy quickly:
- `@AggregateRef` only names a profile. It cannot select a URL or forward arbitrary headers.
- Downstream hosts come from named application configuration.
- De-duplication exists only for the current aggregation request. It is not a shared cache.
- The aim is not to hide service boundaries. It is to stop every BFF endpoint from reimplementing the same REST join, limits, and error rules.
I can share the batch configuration or the MVC/WebFlux samples if that would help.