Federating Remote Data with Hygraph Remote Sources

This guide, part of Hygraph GraphQL Content Federation, shows how to bring data from other systems, such as prices and stock from a commerce platform or ratings from a review service, into Hygraph’s GraphQL API with remote sources. It covers configuring REST and GraphQL remote sources, defining remote fields that call them with values from each entry, keeping credentials safe, handling latency and errors, and deciding which data belongs in remote fields at all.

Headless sites often combine CMS content with data owned by other systems. The usual solution is a backend-for-frontend or an aggregation service that calls both and merges the results. Hygraph’s remote sources move that merge into the content graph: a remote source describes an external API, and a remote field on a model calls it when queried, with parameters taken from the entry, such as a product’s SKU. The frontend sends one query and receives content and remote data together, and editors see remote data next to the entry in the Hygraph app.

A query with a remote fieldThe frontend queries a product with its content fields and a remote price field; Hygraph resolves content from its store and calls the commerce API with the product's SKU for the remote field; the commerce API returns price and stock; Hygraph merges them into one response.FrontendHygraphCommerce APIproduct(slug) { name, commerce { price stock } }resolve content fieldsGET /products/{sku}price, stockcontent + remote data
One query from the frontend; Hygraph calls the remote API on its behalf.

The Problem

An outdoor equipment retailer ran an aggregation service between its frontend, Hygraph and the commerce platform. The service fetched product content from Hygraph, then prices and stock from commerce, merged them and cached the result. It was the part of the stack with the most incidents: cache keys that mixed up locales, timeouts that dropped whole product pages, and a deployment pipeline of its own that nobody enjoyed maintaining. Adding a new commerce field required changes in three places.

How Remote Sources Work

Remote source. A remote source is defined once per project environment with a type, REST or GraphQL, a base URL and headers, for example an authorization header with an API key. For GraphQL sources, Hygraph reads the remote schema; for REST sources, you define the types of the responses in GraphQL SDL.

Remote field. A remote field on a model uses a remote source. For REST, it specifies the method and path, with placeholders filled from the entry’s fields, such as the SKU. For GraphQL, it specifies the remote query and maps entry values to its arguments. The field’s type is the remote response type.

Top-level remote fields. Remote fields can also be added to the root query type, for data that is not tied to an entry, such as a store’s opening hours.

Resolution at query time. Remote fields are resolved only when a query selects them. Queries that do not ask for them pay nothing.

Errors. If the remote API fails, the remote field returns an error in the GraphQL response’s errors, and the content fields are still returned.

Where remote fields fitKinds of external data and whether they suit Hygraph remote fields: frequently changing product prices and stock, review ratings, personalized data, large lists from search services, and slow batch reports.DataSuits remote fields?WhyPrice and stock per productyeskeyed by SKU, fast APIReview rating per productyeskeyed by id, cacheablePersonalized pricesnoper user, belongs in the frontendSearch resultsnonot tied to one entrySlow batch reportsnolatency on every query
Remote fields suit fast, entry-keyed, non-personal data.

Implementation

Define the REST remote source in the schema editor with its base URL and an authorization header, and describe the response type in SDL:

GraphQL
# Custom type definition for the commerce REST source
type CommerceProduct {
  sku: String!
  price: Float
  currency: String
  stock: Int
  available: Boolean
}

Add a remote field commerce to the product model, of type CommerceProduct, with method GET and a path that uses the entry’s SKU, such as /products/{{doc.sku}}. Store the API key in the remote source’s headers, never in the path, and use a key with read-only access to the commerce API.

The frontend queries content and remote data in one request:

TypeScript
// queries/product.ts
export const PRODUCT = /* GraphQL */ `
  query Product($slug: String!, $stage: Stage!, $locales: [Locale!]!) {
    product(where: { slug: $slug }, stage: $stage, locales: $locales) {
      id
      name
      description { json }
      images { url(transformation: { image: { resize: { width: 900 } } }) width height altText }
      sku
      commerce { price currency stock available }
    }
  }
`;

Because GraphQL can return partial data with errors, the fetch helper must not throw when only the remote field failed. Handle that case explicitly:

TypeScript
// lib/product.ts
import { PRODUCT } from "@/queries/product";

export async function getProduct(slug: string, stage: "DRAFT" | "PUBLISHED", locales: string[]) {
  const res = await fetch(process.env.HYGRAPH_ENDPOINT!, {
    method: "POST",
    headers: { "Content-Type": "application/json", Authorization: `Bearer ${process.env.HYGRAPH_READ_TOKEN}` },
    body: JSON.stringify({ query: PRODUCT, variables: { slug, stage, locales } }),
    next: { tags: [`product:slug:${slug}`], revalidate: 300 },   // remote data is refreshed at least every 5 minutes
  });
  const json = await res.json();
  const errors: { path?: (string | number)[]; message: string }[] = json.errors ?? [];
  const onlyRemote = errors.length > 0 && errors.every((e) => e.path?.includes("commerce"));
  if (errors.length && !onlyRemote) throw new Error(`Hygraph: ${errors[0].message}`);
  if (onlyRemote) console.warn(JSON.stringify({ kind: "remote_field_error", slug, message: errors[0].message }));

  const p = json.data?.product;
  return p ? { ...p, commerce: onlyRemote ? null : p.commerce } : null;
}

The page renders price and stock when commerce is present and a neutral “check availability” state when it is not, so a commerce outage never takes product pages down.

Freshness of remote data

Content changes trigger webhooks; remote data changes do not. A price change in the commerce system does not tell Hygraph or the frontend anything. Give pages with remote data a time-based revalidation that matches how stale the data may be, a few minutes for prices, and let the commerce system call the frontend’s revalidation endpoint for urgent changes such as a product going out of stock. For data that must be exact at the moment of purchase, such as the final price in the basket, always ask the commerce system directly at that point.

Latency budget

Every query selecting a remote field waits for the remote API on cache misses. Measure the remote API’s latency percentiles, and set a budget: if its slowest responses are too slow for page rendering, keep the remote field out of page queries and load that data separately, for example client-side after the page renders. Never select remote fields in list queries over many entries, where each entry triggers its own remote call.

Configuration Reference

Item Recommendation Why
Source credentials headers on the remote source, read-only key Not in paths or frontends.
Remote field keys stable identifiers such as SKU Reliable lookups.
Selection only on detail queries No per-entry calls in lists.
Errors handle remote-only errors as partial data Outages degrade gracefully.
Freshness time-based revalidation plus urgent webhooks Remote changes send no CMS events.
Checkout data fetched directly from the source Exactness where it matters.

Gotchas & Edge Cases

  • Missing keys. Entries without a SKU produce failing remote calls; make the key field required, or guard the remote path.
  • Remote schema changes. A changed REST response no longer matches the SDL types; version the remote API or update types together.
  • Environments. Development environments should use a sandbox of the remote API; configure the remote source per environment.
  • Rate limits upstream. Hygraph calls the remote API on behalf of every uncached query; make sure its rate limits can absorb build traffic.
  • Personal data. Remote fields are shared across all readers of a cached query; never use them for per-user data.

Worked Example

The retailer defined a REST remote source for its commerce API and a commerce remote field on products, keyed by SKU, and retired the aggregation service. Product pages queried content and commerce data in one request, degraded to a neutral availability state during a commerce outage instead of failing, and refreshed prices every five minutes with urgent revalidation for stock changes. Adding a new commerce field now meant updating the SDL type and the query, with no separate service to deploy. Incidents related to product data fell sharply in the following quarters.

Places to change when adding a commerce fieldNumber of code locations or services changed to add one new commerce field to product pages, with the aggregation service and with a Hygraph remote field.Aggregation service3 places changedRemote field2 places changed
The remote field removed a whole service from the change path.

When Not to Federate in the CMS

Remote sources are not a replacement for every integration layer. When several frontends need the same merged data with different caching needs, or when merging requires business logic, such as combining prices from several systems or applying promotions, a dedicated service or a backend-for-frontend remains the better place, as discussed in building a BFF layer over a headless CMS API. Remote sources shine when the remote data is simple, keyed by a CMS entry and useful to editors as context. Decide per data type, and document the decision, so the next integration does not default to whichever pattern the last developer preferred.

Rollout Checklist

  • Define remote sources with read-only credentials in headers.
  • Key remote fields by stable identifiers from the entry.
  • Select remote fields only in detail queries.
  • Treat remote-only errors as partial data with a visible fallback.
  • Revalidate pages with remote data on a schedule and on urgent changes.
  • Keep checkout-critical data out of cached remote fields.

Frequently Asked Questions

Are remote fields visible to editors?

Yes, remote data can appear in the entry’s view in the Hygraph app, which helps editors see prices and stock while writing.

Can a remote field call a GraphQL API?

Yes. GraphQL remote sources expose the remote schema, and remote fields map entry values to the remote query’s arguments.

Do remote fields slow down queries that do not select them?

No. They are resolved only when selected.

Can remote fields write to the remote system?

No. They read data at query time; writes go through the remote system’s own API.