Hive Router now supports the Federation
@context and @fromContext directives. After
native composition support, schemas using contexts
can now be served end to end with Hive.
The problem
A deeply nested field sometimes needs data from higher up in the response. Take transactions that should be shown in their owner’s currency:
The subgraph resolving amount needs to know each user’s currency. Without contexts, you’d either
make clients pass the currency as an argument (and repeat it for every user), or carry it through
entity @keys on types that otherwise don’t care about it.
Contexts to the rescue
With contexts, User provides a named context, and the code argument of amount declares that
its value comes from that context:
The code argument is removed from the public API schema. Clients keep querying amount as is,
and the router fills in code from the currency of the nearest User above each transaction.
Alice’s transactions are resolved with code: "USD", Bob’s with code: "EUR".
Highlights
- Nearest ancestor wins. In
users { friends { transactions { amount } } }, each transaction gets its friend’s currency, not the outer user’s. - Interfaces and unions. Contexts can be set on abstract types, and selections can use type
conditions like
... on User { currency } ... on Organization { currency }. - Across subgraphs. The ancestor and the contextual field can live in different subgraphs. The query planner merges contextual fetches into other fetches whenever it’s safe, saving round trips.
One request, no matter how many values
Contexts come with a performance trap. Entities usually share one _entities field, but entities
whose ancestors hold different context values can’t, since each needs a different argument value.
The straightforward approach is to send one subgraph request per distinct value, so a list of users
in 20 currencies turns a single entity fetch into 20 HTTP requests, and the count grows with your
data.
Hive Router groups the entities by their context values and sends every group in a single
subgraph request, each as its own aliased _entities field:
The first alias receives only the transactions of USD users, the second only those of EUR
users. The router maps every entity and error back to its original position, so clients never see
the aliasing.
| Distinct context values | One request per value | Hive Router |
|---|---|---|
| 1 | 1 request | 1 request |
| 2 | 2 requests | 1 request |
| 20 | 20 requests | 1 request |
This goes further than just aliasing:
- It combines with entity batching. Contextual fetches to the same subgraph from different parts of the query share one batched request, with every context group inside it. Contexts and batching together still cost a single round trip.
- Entities are deduplicated per group. Repeated entities with the same context values are sent once.
- No per-request overhead. The query planner compiles each contextual fetch into a template once, and the router writes the aliased query for any number of groups by copying strings, with no parsing or extra caching at execution time.
- Fast grouping. Entities under the same ancestor reuse the previous entity’s group without reading and hashing the context values again.
Combining groups requires nullable contextual arguments. Fetches with a non-null contextual
argument (like String!) send one request per group, all in parallel. See the
guide for
why.