GraphQL Mesh-based Backend for Frontend (BFF) that provides a unified GraphQL API gateway.
This service uses GraphQL Mesh to create a unified GraphQL API gateway that aggregates multiple microservices:
- learn-go (OpenAPI) - Go-based API service (port 8001)
- learn-python (OpenAPI) - Python-based API service (port 8000)
- learn-rust (OpenAPI) - Rust-based API service (port 8080)
┌─────────────────────────────────────────────────────────────┐
│ GraphQL Mesh Gateway │
│ ┌──────────────────────────────────────────────────────┐ │
│ │ Unified GraphQL Schema (Auto-generated + Custom) │ │
│ └──────────────────────────────────────────────────────┘ │
│ │ │
│ ┌────────────┬───────────┼───────────┬──────────────────┐ │
│ │ OpenAPI │ OpenAPI │ OpenAPI │ │ │
│ │ Handler │ Handler │ Handler │ │ │
│ └─────┬──────┴─────┬─────┴─────┬─────┴──────────────────┘ │
│ │ │ │ │
└────────┼────────────┼───────────┼───────────────────────────┘
│ │ │
┌────▼────┐ ┌────▼─────┐ ┌─▼─────────┐
│Learn-Go │ │Learn-Py │ │Learn-Rust │
│ :8001 │ │ :8000 │ │ :8080 │
└─────────┘ └──────────┘ └───────────┘
- Mesh auto-generates GraphQL schema from OpenAPI specs
- No manual type definitions needed for base operations
- Type-safe queries & mutations
- go_ prefix: All learn-go operations (e.g.,
go_healthz,go_ping) - python_ prefix: All learn-python operations (e.g.,
python_healthz,python_info) - rust_ prefix: All learn-rust operations (e.g.,
rust_healthz,rust_version)
- Response caching with configurable TTL
- Per-type cache configuration
- Automatic cache invalidation
- Automatically forwards
x-user-idheaders to all services - Service-specific headers for tracking (
x-service) - Support for custom operation headers
pnpm installcp .env.example .env
# Edit service URLs in .envpnpm devServer starts at http://localhost:8080/graphql
Open browser to http://localhost:8080/graphql for interactive playground.
query HealthCheckAll {
goHealthz: go_healthz {
success
data
timestamp
}
pythonHealthz: python_healthz {
success
data
timestamp
}
rustHealthz: rust_healthz {
success
data
timestamp
}
}query PingAll {
goPing: go_ping
pythonPing: python_ping
rustPing: rust_ping
}query ServiceInfo {
goInfo: go_info {
success
data
timestamp
}
pythonInfo: python_info {
success
data
timestamp
}
rustInfo: rust_info {
success
data
timestamp
}
}mutation EchoMessage {
goEcho: go_echo(body: {message: "Hello from GraphQL"}) {
success
data
timestamp
}
}mesh/
├── .meshrc.yaml # Main Mesh configuration
├── package.json # Dependencies
├── tsconfig.json # TypeScript config
├── .env.example # Environment template
├── Dockerfile # Container image definition
├── k8s/
│ └── chart/ # Helm chart for deployment
│ ├── Chart.yaml
│ ├── values.yaml
│ └── templates/
└── .mesh/ # Generated artifacts (git-ignored)
# Start dev server with hot reload
pnpm dev
# Build for production
pnpm build
# Start production server
pnpm start
# Validate configuration
pnpm validate
# Generate TypeScript types
pnpm generate
# Compose supergraph
pnpm supergraphThe .meshrc.yaml file defines three backend services:
sources:
- name: LearnGo
handler:
openapi:
source: "http://learn-go:8001/openapi.json"
endpoint: "http://learn-go:8001"
operationHeaders:
x-user-id: "{context.headers.x-user-id}"
x-service: "learn-go"
transforms:
- prefix:
value: "go_"
includeRootOperations: true
- name: LearnPython
handler:
openapi:
source: "http://learn-python:8000/openapi.json"
endpoint: "http://learn-python:8000"
operationHeaders:
x-user-id: "{context.headers.x-user-id}"
x-service: "learn-python"
transforms:
- prefix:
value: "python_"
includeRootOperations: true
- name: LearnRust
handler:
openapi:
source: "http://learn-rust:8080/openapi.json"
endpoint: "http://learn-rust:8080"
operationHeaders:
x-user-id: "{context.headers.x-user-id}"
x-service: "learn-rust"
transforms:
- prefix:
value: "rust_"
includeRootOperations: trueTo add a new service, add a source entry in .meshrc.yaml:
sources:
- name: NewService
handler:
openapi:
source: http://new-service:9000/openapi.json
operationHeaders:
Authorization: "Bearer {context.headers.authorization}"
transforms:
- prefix:
value: "newservice_"
includeRootOperations: true| Feature | Direct REST Calls | GraphQL Mesh |
|---|---|---|
| API Type | REST | GraphQL |
| Schema | Manual OpenAPI parsing | Auto-generated |
| Type Safety | Manual types | GraphQL + TypeScript |
| Data Fetching | Multiple requests | Single query |
| Caching | Manual implementation | Plugin (automatic) |
| Error Handling | Per-service format | Unified GraphQL errors |
| Performance | N network calls | Optimized batching |
| Tooling | Swagger UI | GraphQL Playground |
| Learning Curve | Low | Low (declarative) |
Each backend service provides standard REST endpoints that are exposed via GraphQL:
GET /- Root endpointGET /ping- Health pingGET /healthz- Detailed health checkGET /info- Service informationGET /version- Service versionPOST /echo- Echo test endpoint
- REST:
GET /healthz→ GraphQL:query { go_healthz { ... } } - REST:
GET /ping→ GraphQL:query { go_ping } - REST:
POST /echo→ GraphQL:mutation { go_echo(body: {...}) { ... } }
Configure caching in .meshrc.yaml:
cache:
redis:
url: ${REDIS_URL:redis://localhost:6379/0}Enable optional per-type TTL:
plugins:
- responseCache:
ttlPerType:
Query.go_healthz: 60 # 1 minute
Query.python_info: 300 # 5 minutesMesh automatically batches parallel requests to the same service, reducing network overhead.
Filter unnecessary fields to reduce payload size:
transforms:
- filterSchema:
mode: wrap
filters:
- Type.!{Internal*, _*}Build and run the container:
docker build -t mesh:latest .
docker run -p 8080:8080 \
-e REDIS_URL=redis://redis:6379/0 \
mesh:latestDeploy using the provided Helm chart:
helm install mesh k8s/chart \
--set image.repository=your-registry/mesh \
--set image.tag=latest \
--set extraEnv.LEARN_GO_SERVICE_URL=http://learn-go.playground.svc.cluster.local:8001 \
--set extraEnv.LEARN_PYTHON_SERVICE_URL=http://learn-python.playground.svc.cluster.local:8000 \
--set extraEnv.LEARN_RUST_SERVICE_URL=http://learn-rust.playground.svc.cluster.local:8080Set production service URLs in your deployment:
# Service endpoints
LEARN_GO_SERVICE_URL=http://learn-go:8001
LEARN_PYTHON_SERVICE_URL=http://learn-python:8000
LEARN_RUST_SERVICE_URL=http://learn-rust:8080
# Redis cache (optional)
REDIS_URL=redis://redis-cluster:6379/0
REDIS_ENABLED=true
# Server config
PORT=8080
ENABLE_PLAYGROUND=false
CORS_ORIGINS=https://your-domain.comVerify service endpoints are accessible:
# Test learn-go
curl http://localhost:8001/openapi.json
# Test learn-python
curl http://localhost:8000/openapi.json
# Test learn-rust
curl http://localhost:8080/openapi.jsonEnsure services expose valid OpenAPI specifications:
pnpm validateTemporarily disable Redis caching for debugging:
REDIS_ENABLED=false pnpm devCheck that playground is enabled:
ENABLE_PLAYGROUND=true pnpm dev- learn-go - Go-based microservice (port 8001)
- learn-python - Python-based microservice (port 8000)
- learn-rust - Rust-based microservice (port 8080)
MIT