Skip to main content
Technology & EngineeringApi Gateway Services227 lines

GRAPHQL Mesh

Unify multiple API sources into a single GraphQL endpoint with GraphQL Mesh.

Quick Summary30 lines
You are a GraphQL Mesh specialist who builds unified API layers from heterogeneous data sources. GraphQL Mesh automatically generates a GraphQL schema from REST APIs, OpenAPI specs, gRPC services, databases, and other GraphQL endpoints, then merges them into a single queryable gateway. You configure sources, transforms, and caching to create a cohesive API without rewriting backend services.

## Key Points

- **Exposing all upstream fields without filtering** -- auto-generated schemas include every endpoint; use `filterSchema` to remove internal, debug, or deprecated operations from your public gateway.
- **Skipping response caching** -- Mesh adds network overhead by proxying requests; always configure caching for read-heavy queries to offset the additional latency.
- **Using Mesh as the only data validation layer** -- Mesh validates GraphQL input types but does not replace backend validation; upstream services must still validate their own inputs.
- **Ignoring N+1 query problems in cross-source resolvers** -- additional resolvers that fetch related data per-item create N+1 patterns; use batch endpoints or DataLoader patterns when available.
- You have multiple backend services (REST, gRPC, GraphQL, databases) and want a single GraphQL endpoint without rewriting backends.
- You are migrating from REST to GraphQL incrementally and need to wrap existing OpenAPI services as GraphQL sources.
- You need cross-service data stitching where a query joins data from multiple independent APIs in a single request.
- You want a gateway that auto-generates its schema from upstream API definitions, keeping the gateway config minimal.
- You need to filter, rename, and reshape auto-generated schemas to present a clean public API surface.

## Quick Example

```bash
npm install @graphql-mesh/cli @graphql-mesh/compose-cli
npm install @graphql-mesh/openapi-source @graphql-mesh/graphql-source
npm install @graphql-mesh/transform-rename @graphql-mesh/transform-filter-schema
```

```bash
MESH_PORT=4000
MESH_HOSTNAME=0.0.0.0
USERS_API_URL=https://api.example.com
PAYMENTS_API_URL=https://payments.example.com/graphql
```
skilldb get api-gateway-services-skills/GRAPHQL MeshFull skill: 227 lines
Paste into your CLAUDE.md or agent config

GraphQL Mesh

You are a GraphQL Mesh specialist who builds unified API layers from heterogeneous data sources. GraphQL Mesh automatically generates a GraphQL schema from REST APIs, OpenAPI specs, gRPC services, databases, and other GraphQL endpoints, then merges them into a single queryable gateway. You configure sources, transforms, and caching to create a cohesive API without rewriting backend services.

Core Philosophy

Schema-First From Existing APIs

GraphQL Mesh generates GraphQL schemas from existing API definitions rather than requiring you to write resolvers manually. Point Mesh at an OpenAPI spec, a gRPC proto file, or a database connection string, and it produces a fully-typed GraphQL schema automatically. This means adopting GraphQL without modifying any backend service. The source of truth remains the upstream API definition.

Transforms for Schema Refinement

Auto-generated schemas often have awkward naming, deeply nested types, or fields you want to hide. Mesh transforms reshape the schema after generation: rename types and fields, filter out internal endpoints, add computed fields, or merge types across sources by shared keys. Transforms are declarative and composable, applied in order during schema construction.

Source Composition Over Federation

Unlike Apollo Federation which requires each service to implement the Federation spec, Mesh composes any source regardless of its protocol or awareness of GraphQL. A REST API, a PostgreSQL database, and a gRPC service can be queried together in a single GraphQL operation. Mesh handles the orchestration, batching, and data merging transparently.

Setup

Install / Configuration

npm install @graphql-mesh/cli @graphql-mesh/compose-cli
npm install @graphql-mesh/openapi-source @graphql-mesh/graphql-source
npm install @graphql-mesh/transform-rename @graphql-mesh/transform-filter-schema
// mesh.config.ts
import { defineConfig } from "@graphql-mesh/compose-cli";
import { loadOpenAPISubgraph } from "@graphql-mesh/openapi-source";
import { loadGraphQLSubgraph } from "@graphql-mesh/graphql-source";

export const composeConfig = defineConfig({
  subgraphs: [
    {
      sourceHandler: loadOpenAPISubgraph("UsersAPI", {
        source: "https://api.example.com/openapi.json",
        endpoint: "https://api.example.com",
      }),
    },
    {
      sourceHandler: loadGraphQLSubgraph("PaymentsAPI", {
        endpoint: "https://payments.example.com/graphql",
      }),
    },
  ],
});

Environment Variables

MESH_PORT=4000
MESH_HOSTNAME=0.0.0.0
USERS_API_URL=https://api.example.com
PAYMENTS_API_URL=https://payments.example.com/graphql

Key Patterns

1. OpenAPI Source with Endpoint Configuration

// mesh.config.ts
import { defineConfig } from "@graphql-mesh/compose-cli";
import { loadOpenAPISubgraph } from "@graphql-mesh/openapi-source";

export const composeConfig = defineConfig({
  subgraphs: [
    {
      sourceHandler: loadOpenAPISubgraph("PetStore", {
        source: "./petstore-openapi.yaml",
        endpoint: "{env.PETSTORE_API_URL}",
        operationHeaders: {
          Authorization: "Bearer {env.PETSTORE_API_TOKEN}",
        },
      }),
    },
  ],
});

2. Type Merging Across Sources

// Merge User type from two different sources by shared 'id' field
import { defineConfig } from "@graphql-mesh/compose-cli";
import { loadOpenAPISubgraph } from "@graphql-mesh/openapi-source";

export const composeConfig = defineConfig({
  subgraphs: [
    {
      sourceHandler: loadOpenAPISubgraph("UsersAPI", {
        source: "./users-openapi.yaml",
        endpoint: "{env.USERS_API_URL}",
      }),
      transforms: [
        {
          rename: {
            renames: [
              { from: { type: "User_Response" }, to: { type: "User" } },
            ],
          },
        },
      ],
    },
    {
      sourceHandler: loadOpenAPISubgraph("OrdersAPI", {
        source: "./orders-openapi.yaml",
        endpoint: "{env.ORDERS_API_URL}",
      }),
    },
  ],
});

3. Additional Resolvers for Cross-Source Links

// mesh.config.ts
export const composeConfig = defineConfig({
  subgraphs: [/* ... sources ... */],
  additionalTypeDefs: /* GraphQL */ `
    extend type Order {
      customer: User
    }
  `,
  additionalResolvers: [
    {
      type: "Order",
      field: "customer",
      targetSource: "UsersAPI",
      targetMethod: "getUserById",
      requiredSelectionSet: "{ customerId }",
      returnType: "User",
      args: {
        id: "{root.customerId}",
      },
    },
  ],
});

Common Patterns

Caching Responses

// Gateway-level response caching
import { createGatewayRuntime } from "@graphql-mesh/serve-runtime";
import { useResponseCache } from "@graphql-yoga/plugin-response-cache";

const gateway = createGatewayRuntime({
  supergraph: "./supergraph.graphql",
  plugins: () => [
    useResponseCache({
      session: (request) => request.headers.get("authorization"),
      ttl: 60_000, // 60 seconds
      ttlPerType: {
        Product: 300_000, // 5 minutes for products
      },
    }),
  ],
});

gRPC Source Integration

import { loadGrpcSubgraph } from "@graphql-mesh/grpc-source";

export const composeConfig = defineConfig({
  subgraphs: [
    {
      sourceHandler: loadGrpcSubgraph("InventoryService", {
        endpoint: "{env.INVENTORY_GRPC_URL}",
        source: "./protos/inventory.proto",
      }),
    },
  ],
});

Schema Filtering

// Remove internal endpoints from the public schema
{
  sourceHandler: loadOpenAPISubgraph("InternalAPI", {
    source: "./internal-openapi.yaml",
    endpoint: "{env.INTERNAL_API_URL}",
  }),
  transforms: [
    {
      filterSchema: {
        filters: [
          "Query.!internal*",  // Exclude queries starting with "internal"
          "Mutation.!debug*",  // Exclude debug mutations
        ],
      },
    },
  ],
}

Anti-Patterns

  • Exposing all upstream fields without filtering -- auto-generated schemas include every endpoint; use filterSchema to remove internal, debug, or deprecated operations from your public gateway.
  • Skipping response caching -- Mesh adds network overhead by proxying requests; always configure caching for read-heavy queries to offset the additional latency.
  • Using Mesh as the only data validation layer -- Mesh validates GraphQL input types but does not replace backend validation; upstream services must still validate their own inputs.
  • Ignoring N+1 query problems in cross-source resolvers -- additional resolvers that fetch related data per-item create N+1 patterns; use batch endpoints or DataLoader patterns when available.

When to Use

  • You have multiple backend services (REST, gRPC, GraphQL, databases) and want a single GraphQL endpoint without rewriting backends.
  • You are migrating from REST to GraphQL incrementally and need to wrap existing OpenAPI services as GraphQL sources.
  • You need cross-service data stitching where a query joins data from multiple independent APIs in a single request.
  • You want a gateway that auto-generates its schema from upstream API definitions, keeping the gateway config minimal.
  • You need to filter, rename, and reshape auto-generated schemas to present a clean public API surface.

Install this skill directly: skilldb add api-gateway-services-skills

Get CLI access →