v1
Serve
Getting Started

Serve Introduction

GraphQL Mesh’s Serve Runtime allows you to serve your unified GraphQL supergraph schema in any environment that runs JavaScript such as Node.js, Bun, Deno, Google Cloud Functions, Azure Functions, Cloudflare Workers, and more.

This supergraph can be composed by using GraphQL Mesh Compose or any other Federation compliant composition tool such as Apollo Rover.

GraphQL Mesh can also act as a proxy so you can enhance an existing GraphQL API with features like monitoring/tracing caching, rate limiting, some security layers and more.

It can be fetched from either a local file, a remote URL, or a schema registry such as GraphQL Hive or Apollo GraphOS.

To summarize, GraphQL Mesh Serve allows you to:

  • Serve your supergraph in any environment that runs JavaScript
  • Act as an HTTP proxy to enhance an existing GraphQL API
  • Adds an extra layer of security, performance, and monitoring to your API

Installation of CLI

In order to get started, you need to have Node.js installed in your environment. Then, you can install Serve CLI with your favorite package manager:

npm i @graphql-mesh/serve-cli

Basic Usage

Let’s say you have a composed supergraph generated by Mesh Compose or any other compliant tool in supergraph.graphql and you want to serve it.

You can easily serve it by using the following command.

mesh-serve --supergraph=supergraph.graphql
💡

See Configure as a Proxy section if you just want to proxy an existing GraphQL API.

CLI Arguments

💡
All of those can be passed in the configuration file as well
  • --supergraph: Path to the supergraph file in Federation Supergraph format
  • --port or -p: Port to serve the supergraph (default: 4000)
  • --host or -h: Host to serve the supergraph (default: localhost)
  • --fork: Count of workers to spawn. defaults to os.availableParallelism() when NODE_ENV is “production”, otherwise only one (the main) worker

If you want to serve a single subgraph, you can use the parameter below and NOT the one above:

  • --subgraph: Path to the subgraph file in Federation Subgraph format (conflicts with --supergraph)

Environment Variables

These are usually used for easier usage with these two schema registry services. You don’t need any configuration file if you provide these environment variables.

For GraphQL Hive;

  • HIVE_CDN_ENDPOINT: The endpoint of the Hive CDN to fetch the supergraph. See here
  • HIVE_CDN_KEY: The API key provided by GraphQL Hive for Hive CDN. See here
  • HIVE_REGISTRY_TOKEN: The token to push the metrics to GraphQL Hive. See here

For Apollo GraphOS;

  • APOLLO_KEY: The API key provided by Apollo GraphOS to fetch the supergraph. See here
  • APOLLO_GRAPH_REF: The API key provided by Apollo GraphOS to fetch the supergraph. See here

Configuration

If you need to configure the Serve runtime, you need to create or modify the mesh.config.ts file in the root of your project.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  // Configuration here
})

Configure Supergraph

supergraph

You can provide GraphQLSchema, DocumentNode which has the AST of the supergraph or string which is the SDL representation of the supergraph.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  supergraph: './supergraph.graphql',
  // or
  supergraph: 'https://example.com/supergraph.graphql',
  // or you can provide a function that returns a promise of the schema
  supergraph: () =>
    fetch('https://example.com/unified.graphql', {
      headers: {
        Authorization: 'Bearer token'
      }
    }).then(res => res.text())
})
💡

For GraphQL Hive and Apollo GraphOS, you probably don’t need to provide the supergraph option.

polling

Let’s say you have a source that can be changed after a while, it can be a CDN, schema registry or a local file. So by enabling this option, Mesh can poll the source and update the schema automatically.

If a function is provided as in the example above, that function will be called every time the polling interval is reached.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  polling: 5_000 // Polling interval in milliseconds
})

additionalResolvers

You can provide additional resolvers to the supergraph. This can be useful if you want to add a custom resolver to the supergraph, or override the existing one.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  additionalResolvers: {
    Query: {
      hello: () => 'Hello World'
    }
  }
})
💡

TODO: A dedicated page is needed for programmatic version of @resolveTo with Incontext SDK

transports (Advanced usage only)

💡

This is an advanced feature and should be used with caution. Use this only if you know what you are doing.

GraphQL Mesh Transports are the key component of the serve runtime’s execution in GraphQL Mesh. It allows the gateway to communicate with the subgraph. For example @graphql-mesh/transport-rest is used to communicate with the REST subgraphs generated by OpenAPI and JSON Schema source handlers. And GraphQL subgraphs use GraphQL HTTP Transport(@graphql-mesh/transport-http).

GraphQL Mesh looks up the supergraph, and checks the kind of the subgraph, and loads it by checking the @graphql-mesh/transport-{kind} package, then loads it to create an executor for the subgraph. You can see how an example @transport definition looks like here.

And see the implementation of the default transport loading logic here.

You can replace this logic by providing your own transports.

Configure Subgraph

If you want to serve a single subgraph, you can provide the subgraph configuration as well. You can generate subgraphs by using Mesh Compose or any other Federation compliant tool listed here.

subgraph

You can provide GraphQLSchema, DocumentNode which has the AST of the subgraph or string which is the SDL representation of the subgraph

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  subgraph: './subgraph.graphql',
  // or
  subgraph: 'https://example.com/subgraph.graphql',
  // or you can provide a function that returns a promise of the schema
  subgraph: () =>
    fetch('https://example.com/subgraph.graphql', {
      headers: {
        Authorization: 'Bearer token'
      }
    }).then(res => res.text())
})
💡

The rest of the configuration options are the same as the supergraph configuration.

Configure Mesh as a GraphQL Proxy

proxy

HTTP executor options to proxy all incoming requests to another HTTP endpoint.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  proxy: {
    endpoint: 'https://example.com/graphql'
  }
})
endpoint

The URL of the GraphQL endpoint to proxy requests to.

headers

Additional headers to include when querying the original schema It can be a plain object or a function that returns a plain object.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  proxy: {
    endpoint: 'https://example.com/graphql',
    headers: execReq => ({
      // This will pass the original request headers to the proxied request
      authorization: execReq.context.headers.authorization
    })
  }
})
useGETForQueries

Whether to use the GET HTTP method for queries when querying the original schema. In that case, the query will be sent as a query string parameter named query.

method

The HTTP method to use when querying the original schema. Default is POST.

timeout

The timeout in milliseconds for the request to the original schema. There is no timeout by default.

retry

Retry attempts in case of a failure. Default is 0.

credentials

Request Credentials (default: ‘same-origin’) Learn more

skipValidation

By default, Mesh validates the operations on the gateway against the introspected schema. This is recommended to keep it enabled for security reasons. But it brings a performance overhead. If you want to disable this validation and send the operations directly to the upstream service, you can set this option to true.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  proxy: {
    endpoint: 'https://example.com/graphql'
  },
  skipValidation: true
})

Configure Server

sslCredentials for HTTPS

This is the option to provide SSL Credentials for HTTPS Server. If this is provided, Mesh will be served via HTTPS instead of HTTP.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  sslCredentials: {
    key_file_name: 'path/to/key.pem',
    cert_file_name: 'path/to/cert.pem',
    ca_file_name: 'path/to/ca.pem',
    passphrase: 'passphrase',
    dh_params_file_name: 'path/to/dhparams.pem',
    ssl_ciphers: 'ECDHE-R',
    // This translates to SSL_MODE_RELEASE_BUFFERS
    ssl_prefer_low_memory_usage: false
  }
})

browser

This is the option to open the browser automatically when the server is started.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  /**
   * Path to the browser that will be used by `mesh serve` to open a playground window in development mode
   * This feature can be disabled by passing `false`
   */
  browser: true // or `google-chrome` or `firefox` or `safari` or `edge` or `opera` or `vivaldi` or `brave` or `chromium` or `msedge` or `false`
})

port and host

These are the options to configure the port and host of the server in the configuration file rather than passing them as CLI arguments.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  port: 4000,
  host: 'localhost'
})

plugins

This is the option to extend your Mesh Gateway with plugins. GraphQL Mesh uses GraphQL Yoga, and Envelop plugin system which allows you to hook into the different phases of the GraphQL execution to manipulate or track the entire workflow step-by-step.

See dedicated plugins feature page for more information

cors

See dedicated CORS feature page for more information

graphiql

You can configure GraphiQL playground that allows you to play with your GraphQL API.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  graphiql: {
    defaultQuery: 'query { hello }'
  }
})

Learn more about available GraphiQL Options from the dedicated GraphQL Yoga page

TODO: Move those into a dedicated GraphiQL page under Features

landingPage

If you want to disable the landing page, you can set this option to false.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  landingPage: false
})

batching

See dedicated page

fetchAPI (Advanced usage only)

💡

This is an advanced feature and should be used with caution. Use this only if you know what you are doing. Use it on your own risk.

GraphQL Mesh heavily relies on WHATWG Fetch API not only as a HTTP Client but also for handling HTTP Server components. So it uses @whatwg-node/fetch by default which is a platform agnostic implementation of the Fetch API. If you want to use a different Fetch API implementation, you can provide it here.

mesh.config.ts
import fetch from 'node-fetch'
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  fetchAPI: {
    fetch
  }
})

logger

By default, Mesh uses a simple logger that logs to the console by using standard console methods.

Using this option, you can do;

  • Disable logging by providing false
  • Provide your own logger instance
  • Choose a log level
mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
import { createLogger } from 'some-logger-library'
 
export const serveConfig = defineServeConfig({
  logger: createLogger()
  // or
  logger: 'info' // or 'debug' or 'warn' or 'error'
  // or
  logger: false
})

TODO: Move those into a dedicated Logging page under Features GraphQL Mesh uses the same logging mechanism of GraphQL Yoga

graphqlEndpoint

This is the option to provide a custom GraphQL endpoint for the server. By default, it is /graphql.

mesh.config.ts
import { defineConfig as defineServeConfig } from '@graphql-mesh/serve-cli'
 
export const serveConfig = defineServeConfig({
  graphqlEndpoint: '/my-graphql-endpoint'
})

maskedErrors

This is enabled by default for security reasons.

Learn more about Error Masking

cache

Provide a cache storage for the server. By default, Mesh uses an in-memory cache.

Learn more about Caching

pubsub

Provide a PubSub instance for the server. By default, Mesh uses an in-memory PubSub. In order to have a better scalability, you can provide a custom PubSub.

Learn more about Subscriptions and Webhooks to see if you need this option

healthCheckEndpoint and readinessCheckEndpoint

Learn more about Health Check and Readiness Check