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 route
Now, 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 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
;
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 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.
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.