looking for the old supergraph-demo-fed2? It's over here!
Federation 2 is an evolution of the original Apollo Federation with an improved shared ownership model, enhanced type merging, and cleaner syntax for a smoother developer experience. It’s backwards compatible, requiring no major changes to your subgraphs. Try the GA release today!
@defer
Apollo Federation is an architecture for declaratively composing APIs into a unified graph. Each team can own their slice of the graph independently, empowering them to deliver autonomously and incrementally.
Designed in collaboration with the GraphQL community, Federation 2 is a clean-sheet implementation of the core composition and query-planning engine at the heart of Federation, to:
Federation 2 adds:
Apollo Router is our next-generation supergraph runtime:
router --dev
mode for relaxed settings@defer
support!Learn more:
Let's get started!
You'll need:
Install rover
and router
:
Run the following
make
commands within the root project directory after you've cloned the repo.
make deps
With the dependencies above installed and your supergraph's APOLLO_KEY
and APOLLO_GRAPH_REF
ready, you can deploy an entire supergraph with a single command:
Run the following
make
commands within the root project directory after you've cloned the repo and installed the prerequisites.
make run-supergraph
make run-supergraph
does the following:
make up-subgraphs
- deploys subgraphs with docker-compose
make publish-subgraphs
- adds subgraphs to your supergraphmake run-router
- runs Apollo Router with a hot re-loading uplinkthen in a separate window run:
make smoke
which issues several queries including those with new @defer
support!
✅ ALL TESTS PASS!
open http://localhost:4000 to browse the schema and build queries
then shut down the router
with ctrl-c
and for the subgraphs:
make down
That's it!
If this is your first supergraph, let's get started below!
Supergraphs schemas are created by publishing subgraph schemas to the Apollo schema registry, typically when the subgraphs are ready to serve that schema as part of a supergraph.
Publishing subgraphs schemas to the Apollo schema registry does:
Run the following
make
commands within the root project directory after you've cloned the repo and installed the prerequisites.
make up-subgraphs
Which uses this docker-compose.yaml to start the subgraphs:
docker compose \
-f docker-compose.yaml \
-f opentelemetry/docker-compose.otel.yaml \
up -d --build
With docker compose logs
like this:
products | 🚀 Products subgraph ready
users | 🚀 Users subgraph ready
inventory | Completed initialization in 712 ms
reviews | INFO: Application startup complete.
pandas | 🚀 Pandas subgraph ready
Browse the products subgraph on port 4001: http://localhost:4001/
Localhost ports for subgraphs are listed in the docker-compose.yaml
Now we need to create a supergraph in the Apollo schema registry, so we can publish our subgraph schemas into our supergraph!
Register a deployed graph
(free forever)Supergraph
architecture (default)Once your subgraphs are running and a supergraph has been created in Apollo Studio, you can publish the subgraph schemas to your supergraph in the Apollo Registry, where they will be composed into a supergraph schema.
make publish-subgraphs
make publish-subgraphs
will prompt you for an APOLLO_KEY
and APOLLO_GRAPH_REF
that you can obtain from the screen above.
make publish-subgraphs
then issues a rover subgraph publish
for each subgraph with the APOLLO_KEY
and APOLLO_GRAPH_REF
to populate your supergraph for the first time.
---------------------------------------
subgraph: reviews
---------------------------------------
+ rover subgraph publish supergraph-router-v1@current --routing-url http://localhost:4005/graphql --schema subgraphs/reviews/reviews.graphql --name reviews --convert
Publishing SDL to supergraph-router-v1@current (subgraph: reviews) using credentials from the default profile.
A new subgraph called 'reviews' for the 'supergraph-router-v1@current' graph was created
The supergraph for the 'supergraph-router-v1@current' graph was updated with a new schema, composed from the updated 'reviews' subgraph
Monitor your schema delivery progress on on studio: https://studio.apollographql.com/graph/supergraph-router-v1/launches/2c4f1445-4166-4904-bfa3-806f0bc40514?variant=current
rover subgraph publish
can be used by independent teams to publish their subgraphs as part of a larger supergraph. Subgraphs often live in separate VCS repos and rover subgraph check
can be used in the CI for those repos.
With our supergraph schema successfully composed in Studio we can start the stock Apollo Router binary with a minimal router.yaml config file.
No code required!
make run-router
make run-router
does the following:
./router --dev -c ./supergraph/router.yaml --log info
which shows:
make query
which issues the following query that fetches across multiple subgraphs:
query Query {
allProducts {
id
name
sku
createdBy {
email
}
}
}
with results like:
{
"data": {
"allProducts": [
{
"id": "converse-1",
"name": "Converse Chuck Taylor",
"sku": "converse-1",
"createdBy": {
"email": "info@converse.com"
}
},
{
"id": "vans-1",
"name": "Vans Classic Sneaker",
"sku": "vans-1",
"createdBy": {
"email": "info@vans.com"
}
}
]
}
}
http://localhost:4000/ has an embedded Sandbox in Apollo Router.
Apollo Sandbox helps you explore your supergraph and create queries using the query builder.
query Query {
allProducts {
id
name
sku
createdBy {
email
}
}
}
When you're done use ctrl-c
to exit the router
.
Then shutdown the subgraphs with:
make down
That's it!
Composition in Apollo Studio enables multiple teams to independently publish their subgraph schemas after an updated subgraph has been deployed. Studio provides a supergraph CI/CD pipeline with schema checks that can assess the impact of a change using graph-native telemetry from your supergraph router. Composition in Apollo Studio supports basic composition and API Contracts which allows you to create slices of a unified graph (public API, partner API, internal API) for different consumers to use.
Doing local development with your own graph variant (like a branch in GitHub) enables you to see composition errors and browse your schema in Apollo Studio before deploying them to a production supergraph and provides a great developer experience.
Most of the examples in this repo use Composition in Apollo Studio which has some nice developer tooling that is free for all Apollo users.
You can even use many of Studio's dev tools without an Apollo account using Apollo Sandbox. Apollo Router provides an embedded version of Sandbox using router --dev
mode that can even show the query plans from the Router.
Local composition using rover supergraph compose
can be useful for simple local development use cases and air-gapped environments. In most cases Composition in Apollo Studio is preferred even for local development as newly published subgraphs are composed and automatically deployed to your local supergraph router which is listening for changes, so the supergraph automatically updates whenever you rover subgraph publish
a new schema to the schema registry.
This shows how to use rover supergraph compose
with Apollo Router
make run-supergraph-local
make run-supergraph-local
does the following:
make up-subgraphs
- deploys subgraphs with docker-compose
make config
- creates supergraph.yamlmake compose
- composes a local supergraph.graphqlmake run-router-local
- runs Apollo Router with local supergraphthen in a separate window run:
make smoke
which issues several queries including those with new @defer
support!
✅ ALL TESTS PASS!
open http://localhost:4000 to browse the schema and build queries
then shut down the router
with ctrl-c
and for the subgraphs:
make down
That's it!
Apollo Router supports Open Telemetry distributed tracing & metrics, with enhanced Open Telemetry metrics and support for custom resources, labels, and attributes make the Router easier to operate at scale.
Built-in exporters for Prometheus, Jaeger, Zipkin, and Datadog are provided in addition to native support for the OpenTelemetry Protocol (OTLP) that enables a wide variety of observability tooling to work with Apollo Router.
To learn how to use OpenTelemetry (for standard request level metrics) in conjunction with Apollo Studio reporting (for graph-native telemetry with field-level resolution and insights) see the blog post on Open Telemetry for Apollo Federation.
If using Docker for Mac on your laptop, for the best experience:
All of the examples in this repo have Open Telemetry enabled and ready to use with a Zipkin trace viewer at http://localhost:9411.
make run-supergraph
make smoke
shut down the router
with ctrl-c
and for the subgraphs:
make down
You can send Open Telemetry from the Gateway to Honeycomb with the following collector-config.yml:
receivers:
otlp:
protocols:
grpc:
http:
cors_allowed_origins:
- http://*
- https://*
exporters:
otlp:
endpoint: "api.honeycomb.io:443"
headers:
"x-honeycomb-team": "your-api-key"
"x-honeycomb-dataset": "your-dataset-name"
service:
pipelines:
traces:
receivers: [otlp]
exporters: [otlp]
Once the cluster is up and has queries against it (via make smoke
), browse to http://localhost:9090/ and begin querying against metrics pulled from the trace spans.
Example queries:
P95 by service: histogram_quantile(.99, sum(rate(latency_bucket[5m])) by (le, service_name))
Average latency by service and operation (e.g. router/graphql.validate): sum by (operation, service_name)(rate(latency_sum{}[1m])) / sum by (operation, service_name)(rate(latency_count{}[1m]))
RPM by service: sum(rate(calls_total{operation="HTTP POST"}[1m])) by (service_name)
Apollo Router is our next-generation supergraph runtime that supports Apollo Federation (v1 or v2) — a declarative GraphQL architecture that lets you build and operate a modular GraphQL API. The supergraph runtime is what processes all of the incoming API requests from clients and routes them to the subgraphs that make up the overall supergraph.
As a Graph Router, the Apollo Router plays the same role as the Apollo Gateway. The same subgraph schemas and composed supergraph schema can be used in both the Router and the Gateway.
Early benchmarks show that the Router adds less than 10ms of latency to each operation, and it can process 8x the load of the JavaScript Apollo Gateway.
The release of v1.0 takes Apollo Router beyond raw speed with optimizations for client app performance, hardened security, and robust extensibility.
@defer
support in the Router mitigates slow services and works with existing subgraphs written in over 20 languages and frameworks, even if the server itself doesn’t support @defer
.Stock Router binaries are available for Linux, Mac, and Windows. We also ship pre-built docker images and an updated Helm chart. Kubernetes examples examples are also provided for use of kustomize
and other Kubernetes tooling.
make
commands in this project starting withup-
usedocker-compose up
There are docker-compose
examples using the pre-built docker images:
For example:
Run the following
make
commands within the root project directory after you've cloned the repo and installed the prerequisites.
make up-supergraph
make smoke
See that all is well:
✅ ALL TESTS PASS!
Everything can now be shut down with:
make down
@defer
This feature is currently in preview, available in Apollo Router v1.0 and later. Learn about entity-based
@defer
in the Router docs.
Apps need to access essential data with as little latency as possible to improve performance benchmarks like first-content-paint (FCP), time-to-interactive (TTI), and total-blocking-time (TBT). Other less critical data can be returned slower and rendered incrementally while still keeping the user engaged.
However, since multiple REST APIs are often used to fetch data for a single GraphQL query, a single slow REST endpoint can bring an entire query to a halt. Hand tuning individual REST APIs may be needed for critical situations but are often hard to justify for typical roadmap features — leaving you with a difficult choice: slow app performance or slow feature delivery.
With Apollo Router v1.0, apps querying the supergraph can @defer the slow, non-essential parts of a request and have the most critical data returned immediately, with no backend changes to underlying services. The upgraded query planner in v1.0 uses entities to fetch deferred fields from subgraphs and return them incrementally in a new multipart response format.
The best part? Because entity-based @defer is powered by the Router rather than subgraph servers, teams can continue using the same subgraph languages and frameworks they’re comfortable with and @defer just works, even if the subgraph server itself doesn’t offer @defer support.
Apollo Client and Sandbox support App developers can add @defer to queries issued from Apollo Client and Apollo Sandbox and both will now automatically handle the deferred responses. Additionally, when using Sandbox with Apollo Router running locally in --dev mode, it will now show query plans to visualize how deferred queries are fetched.
Let's get started!
Run the following
make
commands within the root project directory after you've cloned the repo and installed the prerequisites.
make up-supergraph-defer
or alternatively
make up-supergraph-defer-local
Issue some queries to verify all is well:
make smoke
which shows:
✅ Introspection Success!
- has @defer support
Running smoke tests ... 🚀 🚀 🚀
✅ ALL TESTS PASS!
@defer
in the RouterBrowse to http://localhost:4000 and issue the following query:
query deferDeliveryExample {
allProducts {
id
name
...MyFragment @defer
}
}
fragment MyFragment on Product {
delivery {
estimatedDelivery
fastestDelivery
}
}
}
this will display the non-deferred content immediately:
and display the deferred query fragments ~ 2 seconds later:
you can now also view local query plans from Apollo Router in Sandbox:
You can also use @defer
with inline fragments:
query DeferDeliveryExampleInline {
allProducts {
... on Product @defer {
delivery {
estimatedDelivery
fastestDelivery
}
}
sku
id
}
}
@defer
in the Router⚠️ The @defer directive is currently at the preview stage in Apollo Client, and is available by installing @apollo/client@next. If you have feedback on it, please let us know via GitHub issues.
The code for this example should already be running via this docker-compose.yaml as part of make up-supergraph-defer
.
http://localhost:3000 shows the deferred query in action.
Non-deferred query fields render immediately:
and display the deferred query fragments ~ 2 seconds later:
@defer
in the Router⚠️ The @defer directive is currently experimental in Apollo Kotlin and enabled for use by default. If you have feedback on it, please let us know via GitHub issues or in the Kotlin Slack community.
Checkout this Apollo Kotlin @defer
demo app:
https://github.com/BoD/DeferDemo
When done, shut everything down with:
make down
@defer
Entity-based @defer
integration tests:
As the Router has been rolled out into more environments we’ve learned about the right integration points and customizations to make the Router work well:
No code required - Apollo ships a standalone Router binary that can be configured using a YAML config file with a new stable v1 configuration schema for things like header forwarding and CORS configuration. Many new features are available in YAML config like traffic shaping support for rate limiting, query deduplication, configurable timeouts and compression. YAML config is a great way to get started with the stock Router binary and is sufficient for many environments.
Lightweight Rhai scripting - New official support for Rhai scripting and a stable v1 API offers a safe and sandboxed way to customize the request flow. Rhai is ideal for common scripting tasks like manipulating strings, processing headers, and mutating request context. Checkout the growing cookbook of example scripts that can be used with the stock Router binary.
Native extensions - With v1.0 we have stabilized all key extension points in the native extension API and enabled more powerful schema-driven extensions to be built using Apollo’s new Rust tooling for GraphQL. Much of the Router itself is built as native extensions that can be used via standard YAML config and Rhai scripting. Native extensions are a good choice when Rhai scripting is not enough and for advanced use cases.
Our goal over time is to identify common customizations and elevate them into standard Router features, so let us know if you have a Router customization or idea that others in the community could benefit from!
Lightweight Rhai scripting - New official support for Rhai scripting and a stable v1 API offers a safe and sandboxed way to customize the request flow. Rhai is ideal for common scripting tasks like manipulating strings, processing headers, and mutating request context. Checkout the growing cookbook of example scripts that can be used with the stock Router binary.
Which uses this test.rhai script:
// At the supergraph_service stage, register callbacks for processing requests
fn supergraph_service(service) {
const request_callback = Fn("process_request"); // This is standard Rhai functionality for creating a function pointer
service.map_request(request_callback); // Register the callback
}
// Generate a log for each request
fn process_request(request) {
let start = apollo_start.elapsed;
// ... Do some processing
let duration = apollo_start.elapsed - start;
log_info(`custom processing took: ${duration}`);
}
Run the following
make
commands within the root project directory after you've cloned the repo and installed the prerequisites.
make run-supergraph-rhai
make smoke
rhai_info
loggingshut down the router
with ctrl-c
and for the subgraphs:
make down
Native extensions - With v1.0 we have stabilized all key extension points in the native extension API and enabled more powerful schema-driven extensions to be built using Apollo’s new Rust tooling for GraphQL. Much of the Router itself is built as native extensions that can be used via standard YAML config and Rhai scripting. Native extensions are a good choice when Rhai scripting is not enough and for advanced use cases.
The router-rust-plugin example is based on the hello-world example.
Config settings for the Plugin
are defined in the router.yaml
plugins:
example.hello_world:
name: "Bob"
Note the plugin gets registered in the code below like this:
register_plugin!("example", "hello_world", HelloWorld);
Which can then be used in the the Plugin
like this:
#[async_trait::async_trait]
impl Plugin for HelloWorld {
type Config = Conf;
async fn new(init: PluginInit<Self::Config>) -> Result<Self, BoxError> {
Ok(HelloWorld {
configuration: init.config,
})
}
fn supergraph_service(&self, service: supergraph::BoxService) -> supergraph::BoxService {
#[cfg(test)]
println!("Hello {}", self.configuration.name);
#[cfg(not(test))]
tracing::info!("Hello {}", self.configuration.name);
// building blocks for your plugin.
ServiceBuilder::new()
// .map_request()
// .map_response()
// .rate_limit()
// .checkpoint()
// .timeout()
.service(service)
.boxed()
}
}
// In order to keep the plugin names consistent,
// we use using the `Reverse domain name notation`
register_plugin!("example", "hello_world", HelloWorld);
Run the following
make
commands within the root project directory after you've cloned the repo and installed the prerequisites.
make run-supergraph-rust-plugin
This will build a custom acme_router
binary:
make smoke
Hello Bob
log messagesshut down the router
with ctrl-c
and for the subgraphs:
make down
There are docker-compose
examples using the pre-built docker images:
make
commands in this project starting withup-
usedocker-compose up
For example:
Run the following
make
commands within the root project directory after you've cloned the repo and installed the prerequisites.
make up-supergraph-gateway
make smoke
See that all is well:
✅ ALL TESTS PASS!
Everything can now be shut down with:
make down
If you get an error like No space left on device
:
#0 33.67 FAILURE: Build failed with an exception.
#0 33.67
#0 33.67 * What went wrong:
#0 33.67 A problem occurred configuring root project 'app'.
#0 33.67 > Could not resolve all files for configuration ':classpath'.
#0 33.68 > Could not download kotlin-compiler-embeddable-1.7.10.jar (org.jetbrains.kotlin:kotlin-compiler-embeddable:1.7.10)
#0 33.68 > Could not get resource 'https://plugins.gradle.org/m2/org/jetbrains/kotlin/kotlin-compiler-embeddable/1.7.10/kotlin-compiler-embeddable-1.7.10.jar'.
#0 33.68 > No space left on device
#0 33.68
run make docker-prune
to free up space:
make docker-prune
which does:
docker image prune -f
docker kill $(docker ps -aq)
docker rm $(docker ps -aq)
docker volume rm $(docker volume ls -qf dangling=true)
then retry the command you were originally trying to execute.