Apollo Router Plugin Creator Create native Rust plugins for Apollo Router. Request Lifecycle ┌────────┐ ┌────────────────┐ ┌────────────────────┐ ┌───────────────────┐ ┌─────────────────────┐ │ Client │ │ Router Service │ │ Supergraph Service │ │ Execution Service │ │ Subgraph Service(s) │ └────┬───┘ └────────┬───────┘ └──────────┬─────────┘ └─────────┬─────────┘ └──────────┬──────────┘ │ │ │ │ │ │ Sends request │ │ │ │ │──────────────────────────▶ │ │ │ │ │ │ │ │ │ │ Converts raw HTTP request to GraphQL/JSON request │ │ │ │ │──────────────────────────────────────────────────────▶ │ │ │ │ │ │ │ │ │ │ Initiates query plan execution │ │ │ │ │───────────────────────────────────▶ │ │ │ │ │ │ │ │ │ ┌par [Initiates sub-operation]───────┐ │ │ │ │ │ │ │ │ │ │ │ │ Initiates sub-operation │ │ │ │ │ │ │────────────────────────────▶ │ │ │ │ │ │ │ │ │ │ │ ├[Initiates sub-operation]╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ │ │ │ │ │ │ │ │ │ Initiates sub-operation │ │ │ │ │ │ │────────────────────────────▶ │ │ │ │ │ │ │ │ │ │ │ ├[Initiates sub-operation]╌╌╌╌╌╌╌╌╌╌╌┤ │ │ │ │ │ │ │ │ │ │ │ │ Initiates sub-operation │ │ │ │ │ │ │────────────────────────────▶ │ │ │ │ │ │ │ │ │ │ │ └────────────────────────────────────┘ │ │ │ │ │ │ │ │ Assembles and returns response │ │ │ │ ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│ │ │ │ │ │ │ │ │ Returns GraphQL/JSON response │ │ │ │ ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│ │ │ │ │ │ │ │ │ Returns HTTP response │ │ │ │ ◀╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌│ │ │ │ │ │ │ │ │ ┌────┴───┐ ┌────────┴───────┐ ┌──────────┴─────────┐ ┌─────────┴─────────┐ ┌──────────┴──────────┐ │ Client │ │ Router Service │ │ Supergraph Service │ │ Execution Service │ │ Subgraph Service(s) │ └────────┘ └────────────────┘ └────────────────────┘ └───────────────────┘ └─────────────────────┘ Service Hooks Service Overview Service Description router_service Runs at the very beginning and very end of the HTTP request lifecycle.For example, JWT authentication is performed within the RouterService.Define router_service if your customization needs to interact with HTTP context and headers. It doesn't support access to the body property supergraph_service Runs at the very beginning and very end of the GraphQL request lifecycle.Define supergraph_service if your customization needs to interact with the GraphQL request or the GraphQL response. For example, you can add a check for anonymous queries. execution_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). subgraph_service Handles communication between the router and your subgraphs.Define subgraph_service to configure this communication (for example, to dynamically add HTTP headers to pass to a subgraph).Whereas other services are called once per client request, this service is called once per subgraph request that's required to resolve the client's request. Each call is passed a subgraph parameter that indicates the name of the corresponding subgraph. Signatures: fn router_service ( & self , service : router :: BoxService ) -> router :: BoxService fn supergraph_service ( & self , service : supergraph :: BoxService ) -> supergraph :: BoxService fn execution_service ( & self , service : execution :: BoxService ) -> execution :: BoxService fn subgraph_service ( & self , name : & str , service : subgraph :: BoxService ) -> subgraph :: BoxService Individual Hooks (Tower Layers) Use ServiceBuilder to compose these hooks within any service: Hook Purpose Sync/Async map_request(fn) Transform request before proceeding Sync map_response(fn) Transform response before returning Sync checkpoint(fn) Validate/filter, can short-circuit Sync checkpoint_async(fn) Async validation, can short-circuit Async buffered() Enable service cloning (needed for async) - instrument(span) Add tracing span around service - rate_limit(num, period) Control request throughput - timeout(duration) Set operation time limit - Choosing a Service Hook By data needed: HTTP headers only → router_service GraphQL query/variables → supergraph_service Query plan → execution_service Per-subgraph control → subgraph_service By timing: Before GraphQL parsing → router_service request After parsing, before planning → supergraph_service request After planning, before execution → execution_service request Before/after each subgraph call → subgraph_service Final response to client → router_service response See references/service-hooks.md for implementation patterns. Quick Start Step 1: Create Plugin File Create a new file src/plugins/my_plugin.rs with required imports: use std :: ops :: ControlFlow ; use apollo_router :: plugin :: { Plugin , PluginInit } ; use apollo_router :: register_plugin ; use apollo_router :: services :: { router , subgraph , supergraph } ; use schemars :: JsonSchema ; use serde :: Deserialize ; use tower :: { BoxError , ServiceBuilder , ServiceExt } ; const PLUGIN_NAME : & str = "my_plugin" ; Step 2: Define Configuration Struct Every plugin needs a configuration struct with Deserialize and JsonSchema derives. The JsonSchema enables configuration validation in editors:
[derive(Debug, Clone, Default, Deserialize, JsonSchema)]
struct MyPluginConfig { /// Enable the plugin enabled : bool , // Add other configuration fields as needed } Step 3: Define Plugin Struct
[derive(Debug)]
struct MyPlugin { configuration : MyPluginConfig , } Step 4: Implement Plugin Trait Implement the Plugin trait with the required Config type and new constructor:
[async_trait::async_trait]
impl Plugin for MyPlugin { type Config = MyPluginConfig ; async fn new ( init : PluginInit < Self :: Config
) -> Result < Self , BoxError
{ Ok ( MyPlugin { configuration : init . config } ) } // Add service hooks based on your needs (see "Choosing a Service Hook" section) } Step 5: Add Service Hooks Choose which service(s) to hook based on your requirements, see Service Overview for details. Example service hook: fn supergraph_service ( & self , service : supergraph :: BoxService ) -> supergraph :: BoxService { if ! self . configuration . enabled { return service ; } ServiceBuilder :: new ( ) . map_request ( | req | { / transform request / req } ) . map_response ( | res | { / transform response / res } ) . service ( service ) . boxed ( ) } Step 6: Register Plugin At the bottom of your plugin file, register it with the router: register_plugin! ( "acme" , "my_plugin" , MyPlugin ) ; Step 7: Add Module to mod.rs In src/plugins/mod.rs , add your module: pub mod my_plugin ; Step 8: Configure in YAML Enable your plugin in the router configuration: plugins : acme.my_plugin : enabled : true Common Patterns For implementation patterns and code examples, see references/service-hooks.md : Enable/disable pattern Request/response transformation ( map_request , map_response ) Checkpoint (early return/short-circuit) Context passing between hooks Async operations ( checkpoint_async , buffered ) Error response builders Examples Apollo Router Examples Located in the Apollo Router plugins directory : Plugin Service Hook Pattern Description forbid_mutations.rs execution_service checkpoint Simple gate on query plan expose_query_plan.rs execution + supergraph Context passing Multi-service coordination cors.rs router_service HTTP layer CORS handling at HTTP level headers/ subgraph_service Layer composition Complex header manipulation For full code examples and testing patterns, see references/examples.md . Prerequisites It is advised to have the rust-best-practices skill installed for writing idiomatic Rust code when developing router plugins. If installed, follow those best practices when generating or modifying plugin code. Resources references/service-hooks.md - Detailed service hook implementations references/existing-plugins.md - Index of existing plugins references/examples.md - Full code examples and testing patterns Apollo Router plugins: https://github.com/apollographql/router/tree/dev/apollo-router/src/plugins