Gateway โ Subgraph Reference
Overview
The ngwenya-gateway is the single entry point for all client traffic. It composes 17 federated subgraphs into a unified supergraph and exposes it on port 30000. Since April 2026, the gateway runs on Hive Gateway (@graphql-hive/gateway, MIT license), replacing the previous Apollo Gateway (ELv2).
| Property | Value |
|---|---|
| Port | 30000 |
| Driver | HiveGatewayDriver (@graphql-yoga/nestjs-federation) |
| Composition | @theguild/federation-composition (runtime v2.9) |
| Supergraph size | ~525K characters |
| Subgraphs | 17 (14 NestJS + 3 Rust) |
| Framework | NestJS 11 + @nestjs/graphql 13 |
IMPORTANT
The gateway performs runtime supergraph composition โ there is no static supergraph.graphql file. The gateway fetches SDL from each subgraph at startup, sanitizes it, and composes the supergraph in-process.
Architecture
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ngwenya-gateway :30000 โ
โ (Hive Gateway + Yoga) โ
โโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโฌโโโโโโโโโโโโโโโโโค
โ malets โproductsโservicesโ ucart โ alerts โ + 9 NestJS โ
โ :3001 โ :3004 โ :3003 โ :3005 โ :3025 โ subgraphs โ
โโโโโโโโโโดโโโโโโโโโผโโโโโโโโโดโโโโโโโโโผโโโโโโโโโดโโโโโโโโโโโโโโโโโค
โ auth โ uchat โ scim / intelligence โ
โ :3008 โ :3017/:3018 โ :3019 / :3026 โ
โโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโโค
โ postgres โ redis โ mongo โ meilisearch โ conduit โ
โ :5432 โ :6379 โ :27017 โ :7700 โ :8448 โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Subgraph Registry
All 17 subgraphs are registered via a config-driven ServiceRegistry:
| # | Subgraph | Port | Technology | Federation Driver |
|---|---|---|---|---|
| 1 | malets | 3001 | NestJS | YogaFederationDriver |
| 2 | services | 3003 | NestJS | YogaFederationDriver |
| 3 | products | 3004 | NestJS | YogaFederationDriver |
| 4 | ucart | 3005 | NestJS | YogaFederationDriver |
| 5 | auth | 3008 | Rust (Axum) | async-graphql |
| 6 | nodes | 3009 | NestJS | YogaFederationDriver |
| 7 | organizations | 3010 | NestJS | YogaFederationDriver |
| 8 | murchases | 3013 | NestJS | YogaFederationDriver |
| 9 | payments | 3014 | NestJS | YogaFederationDriver |
| 10 | search | 3015 | NestJS | YogaFederationDriver |
| 11 | community | 3016 | NestJS | YogaFederationDriver |
| 12 | uchat | 3017 | Rust (Axum) | async-graphql |
| 13 | media | 3006 | NestJS | YogaFederationDriver |
| 14 | blogs | 3007 | NestJS | YogaFederationDriver |
| 15 | alerts | 3025 | NestJS | YogaFederationDriver |
| 16 | scim | 3019 | Rust (Axum) | REST only (no federation) |
| 17 | experiences | 3020 | NestJS | YogaFederationDriver |
Migration from Apollo Gateway
The gateway was migrated from @apollo/gateway (ELv2) to @graphql-hive/gateway (MIT) in the upgrade/nestjs-11 branch for three reasons:
- Licensing โ Apollo Gateway uses ELv2 (not OSI-approved). Hive Gateway is MIT.
- Performance โ Hive Gateway is ~50% faster at p50 and delivers ~2ร throughput under concurrent load.
- NestJS 11 Compatibility โ Hive Gateway natively supports GraphQL Yoga, which is the recommended driver for
@nestjs/graphqlv13.
Key Driver Changes
| Concern | Apollo Gateway | Hive Gateway |
|---|---|---|
| NestJS driver | ApolloGatewayDriver |
HiveGatewayDriver |
| Subgraph driver | ApolloFederationDriver |
YogaFederationDriver |
| Composition | @apollo/composition |
@theguild/federation-composition |
| Response cache | @apollo/server-plugin-response-cache |
@graphql-yoga/plugin-response-cache |
| APQ | Built-in Apollo | @graphql-yoga/plugin-apq |
| Header propagation | willSendRequest() |
propagateHeaders.fromClientToSubgraphs |
| Subscriptions | Separate WS server (port 3027) | Native through federation subgraph |
Federation v2.9 Compatibility
The composition library (@theguild/federation-composition@0.22.2) supports Federation spec up to v2.9. However, @apollo/subgraph@2.13.3 (used by NestJS subgraphs prior to Yoga migration) auto-injects v2.10+ directive definitions.
The Problem
[ERROR] Cannot import unknown element "@listSize"
[ERROR] duplicate directive "@federation__context"
The Solution โ Two-Layer Fix
Layer 1: pnpm patch on @nestjs/graphql@13.3.0
The patch downgrades the default federation importUrl from v2.12 to v2.9 and trims the directive list to v2.9-compatible directives only:
- https://specs.apollo.dev/federation/v2.12
+ https://specs.apollo.dev/federation/v2.9
Layer 2: SDL Sanitization at Gateway
The gateway's fetchSubgraphSdl function strips v2.10+ directive definitions before composition:
// Strip v2.10+ directive definitions that @apollo/subgraph injects
const sanitized = sdl.replace(
/^directive @federation__(context|fromContext|cost|listSize)\b[^}]*$/gm,
''
);
This ensures that even if a subgraph emits v2.10+ directives, they are stripped before reaching the composition engine.
Response Caching & APQ
Response caching and Automatic Persisted Queries are implemented as native Yoga plugins with Redis-backed stores:
plugins: [
useResponseCache({
session: (req) => req.headers.get('x-user-id') ?? null,
cache: createRedisCache({ redis }),
}),
useAPQ({ store: createRedisAPQStore({ redis }) }),
]
See Gateway Tracing & Observability for the full caching architecture, metrics export, and Prometheus integration.
Header Propagation
The gateway forwards authentication and context headers to all subgraphs:
propagateHeaders: {
fromClientToSubgraphs({ request, subgraphRequest }) {
const headers = ['x-user-id', 'x-org-id', 'x-guest-id', 'x-email', 'authorization'];
for (const h of headers) {
const val = request.headers.get(h);
if (val) subgraphRequest.headers.set(h, val);
}
},
}
WebSocket Subscriptions
With Hive Gateway's Yoga driver, GraphQL subscriptions are natively supported through the federated subgraph. The previous architecture required a separate non-federated WS server (port 3027) because Apollo Federation Driver did not support subscriptions.
| Architecture | Subscription Path |
|---|---|
| Current (Hive) | Client โ Gateway :30000/graphql (ws) โ Alerts :3025 |
| Legacy (Apollo) | Client โ Standalone WS :3027 (direct, non-federated) |
The frontend connects subscriptions through the same /graphql endpoint using the ws: protocol upgrade.
WebSocket Authentication
The gateway's graphql-ws server uses an onConnect hook to validate session cookies during the WebSocket handshake:
- Browser sends session cookie automatically on WS upgrade (same-origin)
ws-auth.tsextracts thecookieheader from the HTTP upgrade request- Cookie is validated against the auth service (
POST /auth/validate) - Valid session โ connection accepted, user identity injected into context
- Invalid/missing โ connection rejected at the transport layer (4403 Forbidden)
This ensures unauthenticated users cannot subscribe to notification streams. See Notification Connection Modes for the full auth flow.
Patching Details
The patches/@nestjs__graphql@13.3.0.patch file applies three critical fixes:
| Fix | Purpose |
|---|---|
Explicit exports for lazy-metadata.storage |
Node.js 24+ ESM resolution compatibility |
importUrl downgrade to v2.9 |
Composition library spec alignment |
| Directive list trimming | Remove v2.10+ directives that crash subgraph runtimes |
WARNING
This patch must be maintained when upgrading @nestjs/graphql. If the package version changes, regenerate the patch with pnpm patch @nestjs/graphql@<new-version>.
Startup Orchestration
The scripts/dev/start_services.sh script orchestrates service startup with health-check wait loops:
- Infrastructure (Postgres, Redis, MongoDB, Meilisearch, Conduit) โ 30s timeout
- Rust subgraphs (auth, uchat, scim, intelligence) โ 60s timeout
- NestJS subgraphs (services, products, alerts) โ 120s timeout (webpack compilation)
- Gateway โ starts after all subgraphs are healthy
NestJS subgraphs require ~90โ120s on first boot due to webpack compilation. The wait loops poll the GraphQL endpoint until it responds with a valid __typename.
Benchmarks
Hive Gateway significantly outperforms the legacy Apollo Gateway:
| Metric | Apollo Gateway | Hive Gateway | Improvement |
|---|---|---|---|
| p50 (products) | ~48ms | ~24ms | 2ร faster |
| p95 (products) | ~85ms | ~45ms | ~47% faster |
| Throughput | ~95 req/s | ~180 req/s | ~90% increase |
See benchmark report for the full comparison.
Environment Variables
| Variable | Default | Description |
|---|---|---|
GATEWAY_PORT |
30000 |
Gateway HTTP/WS port |
REDIS_URL |
redis://localhost:6379 |
Redis for caching, APQ, rate limiting |
TRACING_ENABLED |
true |
Master toggle for tracing plugin |
APQ_ENABLED |
true |
Toggle Redis-backed APQ |
RESPONSE_CACHE_ENABLED |
true |
Toggle Redis-backed response caching |
Module Structure
apps/ngwenya-gateway/src/
โโโ app.module.ts # Gateway module with HiveGatewayDriver config + SDL sanitization
โโโ auth.context.ts # Session cookie / Bearer token โ user identity resolution
โโโ ws-auth.ts # WebSocket session cookie validation (onConnect hook)
โโโ rate-limit/ # Dual-window throttling (see /dev/gateway-rate-limiting)
โโโ tracing/ # Response cache, APQ, metrics, health (see /dev/gateway-tracing)
โโโ deprecation/ # Field deprecation tracking
โโโ sitemap/ # XML sitemap generation
โโโ rss/ # RSS feed controller
Related
- Gateway Rate Limiting โ Dual-window throttling, auth uplift, mutation penalties
- Gateway Tracing & Observability โ Response caching, APQ, Prometheus metrics
- Notification Connection Modes โ WebSocket subscription transport architecture
- Local Development Environment โ Full-stack setup, Podman,
maketargets