Docs
Try Apollo Studio

Customizations for the Apollo Router

Extend the Apollo Router with custom functionality


You can write customizations for the Apollo Router to add functionality that isn't offered by default. For example, you can make an external call to fetch authentication data for each incoming request.

Customization types

The Apollo Router supports two types of customizations:

Native Rust plugins require building a custom Apollo Router binary that includes your plugin code. This requires familiarity with building Rust projects. We also recommend looking at the examples provided in the Apollo Router repo.

Which customization type should I use?

If your customization only needs to make basic changes to request or response headers, we recommend first checking whether a Rhai script can accomplish what you need.

If not, the hello world example plugin is a helpful starting point for writing your first native Rust plugin.

How customizations work

Before building an Apollo Router customization, it helps first to understand how the router handles each incoming GraphQL request. During each request's execution, four services in the router communicate with each other as shown:

ClientRouterServiceQueryPlannerServiceExecutionServiceSubgraphService(s)Sends requestFetchesquery planInitiates query plan executionInitiatessub-operationInitiatessub-operationInitiatessub-operationparAssembles and returns responseReturns responseClientRouterServiceQueryPlannerServiceExecutionServiceSubgraphService(s)

As execution proceeds "left to right" from the RouterService to individual SubgraphServices, each service passes the client's original request along to the next service. Similarly, as execution continues "right to left" from SubgraphServices to the RouterService, each service passes the response to the client.

Apollo Router customizations can hook into any combination of these services and modify the request, response, or related metadata as they're passed along.

Service descriptions

Each Apollo Router service has a corresponding function that a customization can define to hook into that service:

ServiceFunctionDescription
RouterServicerouter_service

This service runs at the very beginning and very end of the request lifecycle.

Define router_service if your customization needs to interact at the earliest or latest point possible. For example, this is a good opportunity to perform JWT verification before allowing a request to proceed further.

QueryPlannerServicequery_planning_service

This service handles generating the query plan for each incoming request.

Define query_planning_service if your customization needs to interact with query planning functionality (for example, to log query plan details).

ExecutionServiceexecution_service

This service handles initiating the execution of a query plan after it's been generated.

Define execution_service if your customization includes logic to govern execution (for example, if you want to block a particular query based on a policy decision).

SubgraphServicesubgraph_serviceThis service handles communication between the Apollo Router and your subgraphs. Define subgraph_service to configure this communication (for example, to dynamically add headers to pass to a subgraph).

Most customizations use router_service and/or subgraph_service, whereas the other service functions are less common.

Each service has a request and response data-structure that holds:

  • A context object that was created at the start of the request and is propagated throughout the entire request lifecycle. It holds:
    • The original request from the client
    • A bag of data that can be populated by plugins for communication across the request lifecycle
  • Any other specific data to that service (e.g., query plans and downstream requests/responses)
Edit on GitHub
Previous
Setup
Next
Native Rust plugins