Migrate to GraphQL Mesh v1
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:
{
"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:
{
"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;
serve:
endpoint: /api/graphql # This is the actual endpoint to the API routeNow, let’s integrate our Mesh Gateway in a Next.js API Routes:
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:
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:
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;
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;
serve:
endpoint: /mesh # This is the actual endpoint to the GCP functionYou 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;
import { app } from '@azure/functions'
import { createBuiltMeshHTTPHandler } from '../.mesh'
const meshHTTP = createBuiltMeshHTTPHandler()
app.http('graphql', {
methods: ['GET', 'POST'],
authLevel: 'anonymous',
handler: meshHTTP
})We need to configure Mesh CLI to generate artifacts for the function’s path;
serve:
endpoint: /api/mesh # This is the actual endpoint to the GCP functionDeploy 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.
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.
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.
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.
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 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.