Apollo Router Quickstart

Run the router locally


Hello! Let's run Apollo Router for the first time, using the simple scenario of developing locally.

In this guide, you will:

  • Download and run the router as a binary.

  • Create a supergraph schema.

  • Create a router YAML configuration file.

  • Run the router in development mode.

  • Make a query to the running router.

1. Download the router

Let's start by downloading and running the router locally.

  1. Download the latest version of the router binary with a single command line:

    Bash
    curl -sSL https://router.apollo.dev/download/nix/latest | sh
    Download a specific router version
    To download and install a specific version of router, set the version in the download URL path.For example, to download router v2.0.0:
    Bash
    curl -sSL https://router.apollo.dev/download/nix/v2.0.0 | sh

    Optionally, go to router releases in GitHub to download and extract a bundle.

  2. Check that your router downloaded successfully by running the router binary from your project's root directory:

    Bash
    ./router --version

2. Create a supergraph schema

A router needs a schema for the federated graph, or supergraph, that it's orchestrating. This guide uses an example supergraph schema, which you download and provide to the router.

The example supergraph schema is composed of four subgraphs: accounts, inventory, products, and reviews. It outlines the types (Query, Mutation, Product, Review, User) and their fields, and it specifies which subgraph is responsible for resolving each piece of data using Apollo Federation directives (@join__*, @link).

  1. From your project's root directory, run the following to download and save an example supergraph schema:

Bash
curl -sSL https://supergraph.demo.starstuff.dev/ > supergraph.graphql
Example supergraph schema contents
GraphQL
supergraph.graphql
1schema
2  @link(url: "https://specs.apollo.dev/link/v1.0")
3  @link(url: "https://specs.apollo.dev/join/v0.3", for: EXECUTION) {
4  query: Query
5  mutation: Mutation
6}
7
8directive @join__enumValue(graph: join__Graph!) repeatable on ENUM_VALUE
9
10directive @join__field(
11  graph: join__Graph
12  requires: join__FieldSet
13  provides: join__FieldSet
14  type: String
15  external: Boolean
16  override: String
17  usedOverridden: Boolean
18) repeatable on FIELD_DEFINITION | INPUT_FIELD_DEFINITION
19
20directive @join__graph(name: String!, url: String!) on ENUM_VALUE
21
22directive @join__implements(
23  graph: join__Graph!
24  interface: String!
25) repeatable on OBJECT | INTERFACE
26
27directive @join__type(
28  graph: join__Graph!
29  key: join__FieldSet
30  extension: Boolean! = false
31  resolvable: Boolean! = true
32  isInterfaceObject: Boolean! = false
33) repeatable on OBJECT | INTERFACE | UNION | ENUM | INPUT_OBJECT | SCALAR
34
35directive @join__unionMember(
36  graph: join__Graph!
37  member: String!
38) repeatable on UNION
39
40directive @link(
41  url: String
42  as: String
43  for: link__Purpose
44  import: [link__Import]
45) repeatable on SCHEMA
46
47scalar join__FieldSet
48
49enum join__Graph {
50  ACCOUNTS
51    @join__graph(name: "accounts", url: "https://accounts.demo.starstuff.dev/")
52  INVENTORY
53    @join__graph(
54      name: "inventory"
55      url: "https://inventory.demo.starstuff.dev/"
56    )
57  PRODUCTS
58    @join__graph(name: "products", url: "https://products.demo.starstuff.dev/")
59  REVIEWS
60    @join__graph(name: "reviews", url: "https://reviews.demo.starstuff.dev/")
61}
62
63scalar link__Import
64
65enum link__Purpose {
66  """
67  `SECURITY` features provide metadata necessary to securely resolve fields.
68  """
69  SECURITY
70
71  """
72  `EXECUTION` features provide metadata necessary for operation execution.
73  """
74  EXECUTION
75}
76
77type Mutation @join__type(graph: PRODUCTS) @join__type(graph: REVIEWS) {
78  createProduct(upc: ID!, name: String): Product @join__field(graph: PRODUCTS)
79  createReview(upc: ID!, id: ID!, body: String): Review
80    @join__field(graph: REVIEWS)
81}
82
83type Product
84  @join__type(graph: ACCOUNTS, key: "upc", extension: true)
85  @join__type(graph: INVENTORY, key: "upc")
86  @join__type(graph: PRODUCTS, key: "upc")
87  @join__type(graph: REVIEWS, key: "upc") {
88  upc: String!
89  weight: Int
90    @join__field(graph: INVENTORY, external: true)
91    @join__field(graph: PRODUCTS)
92  price: Int
93    @join__field(graph: INVENTORY, external: true)
94    @join__field(graph: PRODUCTS)
95  inStock: Boolean @join__field(graph: INVENTORY)
96  shippingEstimate: Int @join__field(graph: INVENTORY, requires: "price weight")
97  name: String @join__field(graph: PRODUCTS)
98  reviews: [Review] @join__field(graph: REVIEWS)
99  reviewsForAuthor(authorID: ID!): [Review] @join__field(graph: REVIEWS)
100}
101
102type Query
103  @join__type(graph: ACCOUNTS)
104  @join__type(graph: INVENTORY)
105  @join__type(graph: PRODUCTS)
106  @join__type(graph: REVIEWS) {
107  me: User @join__field(graph: ACCOUNTS)
108  recommendedProducts: [Product] @join__field(graph: ACCOUNTS)
109  topProducts(first: Int = 5): [Product] @join__field(graph: PRODUCTS)
110}
111
112type Review @join__type(graph: REVIEWS, key: "id") {
113  id: ID!
114  body: String
115  author: User @join__field(graph: REVIEWS, provides: "username")
116  product: Product
117}
118
119type User
120  @join__type(graph: ACCOUNTS, key: "id")
121  @join__type(graph: REVIEWS, key: "id") {
122  id: ID!
123  name: String @join__field(graph: ACCOUNTS)
124  username: String
125    @join__field(graph: ACCOUNTS)
126    @join__field(graph: REVIEWS, external: true)
127  reviews: [Review] @join__field(graph: REVIEWS)
128}

3. Create a router config

The router's many features are configurable via a YAML configuration file. You set your options declaratively in YAML, then point your router to it at startup.

Let's customize a common setting: the router's supergraph listen address. It's the network address and port on which the router receives client requests. By default the address is 127.0.0.1:4000. As an exercise, let's change the port to 5555.

  1. In your same working directory, create a file named router.yaml. Open it for editing.

  2. Add the following configuration that sets supergraph.listen to 127.0.0.1:5555:

YAML
router.yaml
1supergraph:
2  listen: 127.0.0.1:5555

4. Run the router

Let's run the router in dev mode, using both the supergraph schema and YAML configuration files you created:

  1. Run the router with these command-line options:

    • --dev enables dev mode

    • --config provides the path to your YAML configuration file

    • --supergraph provides the path to your supergraph schema

    sh
    ./router --dev --config router.yaml --supergraph supergraph.graphql
    About dev mode
    Running router with --dev is the same as using the following configuration:
    YAML
    Same configuration as --dev
    1sandbox:
    2  enabled: true
    3homepage:
    4  enabled: false
    5supergraph:
    6  introspection: true
    7include_subgraph_errors:
    8  all: true
    9plugins:
    10  # Enable with the header, Apollo-Expose-Query-Plan: true
    11  experimental.expose_query_plan: true
    Learn more about router dev mode.
  2. Check that your router is running, with output similar to the example:

    Example router output
    sh
    2025-04-25T21:54:05.910202Z INFO  Running with *development* mode settings which facilitate development experience (e.g., introspection enabled)
    2025-04-25T21:54:05.981114Z INFO  Apollo Router v2.1.3 // (c) Apollo Graph, Inc. // Licensed as ELv2 (https://go.apollo.dev/elv2)
    2025-04-25T21:54:05.981141Z INFO  Anonymous usage data is gathered to inform Apollo product development.  See https://go.apollo.dev/o/privacy for details.
    2025-04-25T21:54:05.985764Z INFO  state machine transitioned event="UpdateLicense(Unlicensed)" state=Startup previous_state="Startup"
    2025-04-25T21:54:05.987948Z INFO  state machine transitioned event="UpdateConfiguration(<redacted>)" state=Startup previous_state="Startup"
    2025-04-25T21:54:05.988144Z INFO  state machine transitioned event="NoMoreLicense" state=Startup previous_state="Startup"
    2025-04-25T21:54:06.010232Z INFO  Health check exposed at http://127.0.0.1:8088/health
    2025-04-25T21:54:06.010717Z WARN  Connector debugging is enabled, this may expose sensitive information.
    2025-04-25T21:54:06.405064Z INFO  GraphQL endpoint exposed at http://127.0.0.1:5555/ 🚀
    2025-04-25T21:54:06.405628Z INFO  You're using some "experimental" features of the Apollo Router (those which have their configuration prefixed by "experimental_").
    We may make breaking changes in future releases. To help us design the stable version we need your feedback.
    Here is a list of links where you can give your opinion:
    
        - experimental_response_trace_id: https://github.com/apollographql/router/discussions/2147
    
    For more information about launch stages, please see the documentation here: https://www.apollographql.com/docs/resources/product-launch-stages/
    2025-04-25T21:54:06.406568Z INFO  state machine transitioned event="UpdateSchema(<redacted>)" state=Running previous_state="Startup"
    2025-04-25T21:54:06.406591Z INFO  state machine transitioned event="NoMoreConfiguration" state=Running previous_state="Running"

5. Make a query

When the router runs in dev mode, it hosts an Apollo Sandbox automatically. Sandbox has a browser-based IDE, Explorer, that you can use to write and send real GraphQL queries to your graph.

  1. Go to the URL your router is running at, http://127.0.0.1:5555. Sandbox should be running there.

  2. Copy and paste the example query into the Operation pane of Explorer:

    GraphQL
    1query Query {
    2  recommendedProducts {
    3    inStock
    4    name
    5    price
    6    reviews {
    7      author {
    8        name
    9      }
    10    }
    11  }
    12}
  3. Click Query to run the query, then check for its response in the Response pane.

    Apollo Sandbox IDE showing successful query and response at the end of the router quickstart

That's it! You've successfully sent a query to a router running a development graph and received a response.

Next steps

Now that you've run the router locally, explore more about deployment and configuration:

Feedback

Edit on GitHub

Ask Community