Catch the highlights of GraphQLConf 2023! Click for recordings. Or check out our recap blog post.
Docs
Getting Started
Deploy a Mesh Gateway

How to: Deploy a GraphQL Mesh Gateway

Thanks to its flexible architecture and embedded server relying on GraphQL Yoga and Envelop, GraphQL Mesh can be deployed anywhere!

We already saw that mesh dev could be used for local development.

Similarly, Mesh provides a mesh start CLI command for production environments.

mesh start can be used for all environments supporting starting a web server (Heroku, Digital Ocean, etc).

Setup Mesh on a Serverless environment requires some integration work, detailed below.

Deploy Mesh with mesh start on Node.js

While mesh dev handles the generation of the SDK code, mesh start expects to load the Gateway schema and runtime from the .mesh/ folder.

This mechanism helps:

  • reducing the start time of the server: no build step is required
  • preventing starting failure if one of the Sources is unreachable: we don't fetch the API definition file at startup, ensuring that the fetched definitions are validated at build time

To deploy a Mesh Gateway, you need to ensure that mesh build is called during the deployment, for example, with a prebuild step:

package.json
{
  "scripts": {
    "start": "mesh start",
    // will be run during deployment
    "build": "mesh build"
  }
}

For more information about the embedded Mesh server configuration, please refer to the serve reference documentation.

Deploy Mesh on Serverless

Serverless deployment requires some integration since we cannot keep the mesh start server running.

Deploy Mesh on Vercel with Next.js API Routes

First, let's ensure that mesh build will be run during deployment.

Vercel - list most platforms, and run yarn build for deployment. For this reason, we will add a prebuild step:

package.json
{
  "scripts": {
    "start": "mesh start",
    // will be run during deployment
    "prebuild": "mesh build"
  }
}

Then, we have to update Mesh configuration to let Mesh know the actual endpoint;

.meshrc.yml
serve:
  endpoint: /api/graphql # This is the actual endpoint to the API route

Now, let's integrate our Mesh Gateway in a Next.js API Routes:

website/src/pages/api/graphql/index.ts
import { createBuiltMeshHTTPHandler } from './.mesh'
 
export default createBuiltMeshHTTPHandler()

Path ./.mesh refers to built Mesh folder that should be available in your project root (together with your project package.json)

Deploy Mesh on AWS Lambda

Similarly to regular and Vercel deployment, we will need to add the mesh build command in the build step.

Then, we can create a Lambda as it follows:

graphql.ts
import { APIGatewayEvent, APIGatewayProxyResult, Context } from 'aws-lambda'
import type { Handler } from '@aws-cdk/aws-lambda'
import { createBuiltMeshHTTPHandler } from './.mesh'
 
interface ServerContext {
  event: APIGatewayEvent
  lambdaContext: Context
}
 
const meshHTTP = createBuiltMeshHTTPHandler<ServerContext>()
 
export async function handler(
  event: APIGatewayEvent,
  lambdaContext: Context
): Promise<APIGatewayProxyResult> {
  const url = new URL(event.path, 'http://localhost')
  if (event.queryStringParameters != null) {
    for (const name in event.queryStringParameters) {
      const value = event.queryStringParameters[name]
      if (value != null) {
        url.searchParams.set(name, value)
      }
    }
  }
 
  const response = await meshHTTP.fetch(
    url,
    {
      // For v1.0 you should use event.httpMethod
      method: event.requestContext.http.method,
      headers: event.headers as HeadersInit,
      body: event.body
        ? Buffer.from(event.body, event.isBase64Encoded ? 'base64' : 'utf8')
        : undefined
    },
    {
      event,
      lambdaContext
    }
  )
 
  const responseHeaders: Record<string, string> = Object.fromEntries(response.headers.entries())
 
  return {
    statusCode: response.status,
    headers: responseHeaders,
    body: await response.text(),
    isBase64Encoded: false
  }
}

Deploy Mesh on Cloudflare Workers

Similarly to regular and Vercel deployment, we will need to add the mesh build command in the build step.

Then:

listener.ts
import { createBuiltMeshHTTPHandler } from './.mesh'
 
// Pass Mesh's HTTP handler as an event listener
self.addEventListener('fetch', createBuiltMeshHTTPHandler())

You can see the following examples for more details:

Also you can see how to setup KV as a cache storage in GraphQL Mesh here.

Deploy Mesh on Apache OpenWhisk

You can see our example that shows how to setup an OpenWhisk action for GraphQL Mesh. OpenWhisk Example

Deploy Mesh on GCP Cloud Functions

Similarly to regular and Vercel deployment, we will need to add the mesh build command in the build step.

Then assuming that your function's name is mesh;

index.ts
import type { IncomingMessage, ServerResponse } from 'node:http'
import { createBuiltMeshHTTPHandler } from './.mesh'
 
const meshHTTP = createBuiltMeshHTTPHandler()
 
export function mesh(req: IncomingMessage, res: ServerResponse) {
  // GCP doesn't expose the full path so we need to patch it
  req.url = '/mesh' + req.url
  return meshHTTP(req, res)
}

We need to configure Mesh CLI to generate artifacts for the function's path;

.meshrc.yml
serve:
  endpoint: /mesh # This is the actual endpoint to the GCP function

You can see our example that shows how to setup a Cloud Function for GraphQL Mesh. Cloud Functions Example

Deploy on Azure Functions

Similarly to regular and Vercel deployment, we will need to add the mesh build command in the build step.

Then assuming that your function's name is mesh;

index.ts
import type { IncomingMessage, ServerResponse } from 'node:http'
import { createBuiltMeshHTTPHandler } from './.mesh'
 
const meshHTTP = createBuiltMeshHTTPHandler()
 
const httpTrigger: AzureFunction = async function (
  context: Context,
  req: HttpRequest
): Promise<void> {
  context.log('HTTP trigger function processed a request.')
 
  const response = await meshHTTP.fetch(req.url, {
    method: req.method?.toString(),
    body: req.rawBody,
    headers: req.headers
  })
 
  const headersObj = Object.fromEntries(response.headers.entries())
 
  context.log('GraphQL Mesh response headers:', headersObj)
 
  const responseText = await response.text()
  context.log('GraphQL Mesh response text:', responseText)
 
  context.res = {
    status: response.status,
    body: responseText,
    headers: headersObj
  }
}
 
export default httpTrigger

We need to configure Mesh CLI to generate artifacts for the function's path;

.meshrc.yml
serve:
  endpoint: /api/mesh # This is the actual endpoint to the GCP function

Deploy on Node.js

Mesh as an Express route

Similarly to regular and Vercel deployment, we will need to add the mesh build command in the build step.

index.ts
import { createBuiltMeshHTTPHandler } from './.mesh'
 
const app = express()
app.use('/graphql', createBuiltMeshHTTPHandler())

Mesh as a Fastify route

Similarly to regular and Vercel deployment, we will need to add the mesh build command in the build step.

index.ts
import { createBuiltMeshHTTPHandler } from './.mesh'
 
const app = fastify()
 
const meshHttp = createBuiltMeshHTTPHandler()
 
app.route({
  url: '/graphql',
  method: ['GET', 'POST', 'OPTIONS'],
  async handler(req, reply) {
    // Second parameter adds Fastify's `req` and `reply` to the GraphQL Context
    const response = await meshHttp.handleNodeRequest(req, {
      req,
      reply
    })
    response.headers.forEach((value, key) => {
      reply.header(key, value)
    })
 
    reply.status(response.status)
 
    const reader = response.body.getReader()
 
    while (true) {
      const { done, value } = await reader.read()
      if (done) break
      reply.send(value)
    }
 
    return reply
  }
})

Mesh as a Node.js request handler

Similarly to regular and Vercel deployment, we will need to add the mesh build command in the build step.

index.ts
import { createServer } from 'node:http'
import { createBuiltMeshHTTPHandler } from './.mesh'
 
const server = createServer(createBuiltMeshHTTPHandler())
server.listen(4000)

Mesh as a Koa route

Similarly to regular and Vercel deployment, we will need to add the mesh build command in the build step.

index.ts
import { createBuiltMeshHTTPHandler } from './.mesh'
 
const app = new Koa()
 
const meshHttp = createBuiltMeshHTTPHandler()
app.use(async ctx => {
  // Second parameter adds Koa's context into GraphQL Context
  const response = await meshHttp.handleNodeRequest(ctx.req, ctx)
 
  // Set status code
  ctx.status = response.status
 
  // Set headers
  response.headers.forEach((value, key) => {
    ctx.append(key, value)
  })
 
  // Converts ReadableStream to a NodeJS Stream
  ctx.body = response.body
})

Mesh and SvelteKit

Similarly to regular and Vercel deployment, we will need to add the mesh build command in the build step.

index.ts
import { createBuiltMeshHTTPHandler } from './.mesh'
 
const meshHttp = createBuiltMeshHTTPHandler()
 
export { meshHttp as get, meshHttp as post }

Mesh and Docker

A GraphQL Mesh Gateway should be treated like any Node.js project while keeping in mind that a mesh build step should be added to the deployment steps.

💡

Any Node.js Docker image is suitable for GraphQL Mesh deployment: https://hub.docker.com/_/node.