---
description:
  Learn how to deploy GraphQL Mesh anywhere. Use mesh dev for local development and mesh start for
  production. Deploy Mesh with ease on Vercel, AWS Lambda, Cloudflare Workers and more!
---

import { Callout } from '@theguild/components'

# How to: Deploy a GraphQL Mesh Gateway

Thanks to its flexible architecture and embedded server relying on
[GraphQL Yoga](https://graphql-yoga.com) and [Envelop](https://envelop.dev), **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:

```jsonc filename="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](/docs/getting-started/customize-mesh-server#configuration-serve-reference).

## 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:

```json filename="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;

```yaml filename=".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:

```ts filename="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:

```ts filename="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:

```ts filename="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:

- [Response Caching on a REST API](https://github.com/ardatan/graphql-mesh/tree/master/examples/cloudflare-workers)
- [Response Caching on a GraphQL API](https://github.com/ardatan/graphql-mesh/tree/master/examples/spacex-cfw)

Also you can see how to setup _KV_ as a cache storage in GraphQL Mesh [here](/docs/cache/cfwKv).

### Deploy Mesh on Apache OpenWhisk

You can see our example that shows how to setup an OpenWhisk action for GraphQL Mesh.
[OpenWhisk Example](https://github.com/ardatan/graphql-mesh/tree/master/examples/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`;

```ts filename="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;

```yaml filename=".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](https://github.com/ardatan/graphql-mesh/tree/master/examples/gcp-functions)

### 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`;

```ts filename="index.ts"
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;

```yaml filename=".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.

```ts filename="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.

```ts filename="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.

```ts filename="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.

```ts filename="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 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.

<Callout>
  Any Node.js Docker image is suitable for GraphQL Mesh deployment:
  [https://hub.docker.com/_/node](https://hub.docker.com/_/node).
</Callout>
