On this page

gRPC / Protobuf

GraphQL Mesh gRPC Handler allows loading gRPC definition files and using reflection, with custom metadata for authorization. Learn more now!

image

This Handler allows you to load gRPC definition files (.proto).

npm i @omnigraph/grpc

Then you can use it in your Mesh configuration:

mesh.config.ts
import loadGrpcSubgraph from '@omnigraph/grpc'
import { defineConfig } from '@graphql-mesh/compose-cli'

export const composeConfig = defineConfig({
  subgraphs: [
    {
      sourceHandler: loadGrpcSubgraph('MyGrpcApi', {
        // gRPC Endpoint
        endpoint: 'localhost:50051',
        // Path to the proto file
        source: 'grpc/proto/Example.proto',
        // or
        source: {
          file: 'grpc/proto/Example.proto',
          load: {
            defaults: true,
            includeDirs: ['grpc/proto']
          }
        }

        // Request timeout in milliseconds
        requestTimeout: 200_000,

        // Use HTTPS instead HTTP for gRPC connection
        useHTTPS: false,

        // Use SSL credentials for gRPC connection
        credentialsSsl: {
          rootCA: 'path/to/rootCA.pem',
          certChain: 'path/to/certChain.pem',
        },

        // Prefix to collect Query method default: list, get
        prefixQueryMethod: ['list', 'get'],

        // Select certain fields as Query or Mutation
        // This overrides `prefixQueryMethod`
        selectQueryOrMutationField: [
          {
            // You can use a pattern matching with *
            fieldName: '*RetrieveMovies',
            type: 'Query',
          },
          // Or you can use a specific field name
          // This will make the field GetMovie available as a Mutation
          // Because it would be Query because of `prefixQueryMethod`
          {
            fieldName: 'GetMovie',
            type: 'Mutation'
          }
        ]

        // Headers for the protobuf if URL is provided
        schemaHeaders: {
          'x-api-key': 'my-api-key'
        }
      })
    }
  ]
})

Use Reflection instead of proto files

If you have configured reflection in your gRPC server, you don’t need to provide source.

mesh.config.ts
import { defineConfig } from '@graphql-mesh/compose-cli'
import loadGrpcSubgraph from '@omnigraph/grpc'

export const composeConfig = defineConfig({
  subgraphs: [
    {
      sourceHandler: loadGrpcSubgraph('MyGrpcApi', {
        endpoint: 'localhost:50051'
      })
    }
  ]
})

Custom Metadata for Authorization

Here you can use metaData field to pass some custom metadata from the context.

mesh.config.ts
import { defineConfig } from '@graphql-mesh/compose-cli'
import loadGrpcSubgraph from '@omnigraph/grpc'

export const composeConfig = defineConfig({
  subgraphs: [
    {
      sourceHandler: loadGrpcSubgraph('MyGrpcApi', {
        endpoint: 'localhost:50051',
        metaData: {
          authorization: "Bearer {context.headers['x-my-token']}",
          someStaticValue: 'MyStaticValue'
        }
      })
    }
  ]
})

Reflection Metadata (reflectionMetadata)

When using gRPC reflection (no source), use reflectionMetadata to send metadata only on reflection requests — for example routing headers required by your infrastructure:

mesh.config.ts
import { defineConfig } from '@graphql-mesh/compose-cli'
import loadGrpcSubgraph from '@omnigraph/grpc'

export const composeConfig = defineConfig({
  subgraphs: [
    {
      sourceHandler: loadGrpcSubgraph('MyGrpcApi', {
        endpoint: 'localhost:50051',
        reflectionMetadata: {
          'grpc-service': 'proto.MyGrpcService',
          authorization: 'Bearer {env.REFLECTION_TOKEN}'
        }
      })
    }
  ]
})

Channel Options & Timeouts

  • requestTimeout sets a per-call deadline (milliseconds from the start of each request).
  • channelOptions are passed to the gRPC client constructor (message size limits, keepalive, etc.):
mesh.config.ts
import { defineConfig } from '@graphql-mesh/compose-cli'
import loadGrpcSubgraph from '@omnigraph/grpc'

export const composeConfig = defineConfig({
  subgraphs: [
    {
      sourceHandler: loadGrpcSubgraph('MyGrpcApi', {
        endpoint: 'localhost:50051',
        requestTimeout: 5000,
        channelOptions: {
          'grpc.max_receive_message_length': 10_000_000,
          'grpc.keepalive_time_ms': 10_000,
          'grpc.keepalive_timeout_ms': 5_000,
          'grpc.keepalive_permit_without_calls': 1
        }
      })
    }
  ]
})