Developer Docs

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:

  1. Licensing โ€” Apollo Gateway uses ELv2 (not OSI-approved). Hive Gateway is MIT.
  2. Performance โ€” Hive Gateway is ~50% faster at p50 and delivers ~2ร— throughput under concurrent load.
  3. NestJS 11 Compatibility โ€” Hive Gateway natively supports GraphQL Yoga, which is the recommended driver for @nestjs/graphql v13.

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:

  1. Browser sends session cookie automatically on WS upgrade (same-origin)
  2. ws-auth.ts extracts the cookie header from the HTTP upgrade request
  3. Cookie is validated against the auth service (POST /auth/validate)
  4. Valid session โ†’ connection accepted, user identity injected into context
  5. 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:

  1. Infrastructure (Postgres, Redis, MongoDB, Meilisearch, Conduit) โ€” 30s timeout
  2. Rust subgraphs (auth, uchat, scim, intelligence) โ€” 60s timeout
  3. NestJS subgraphs (services, products, alerts) โ€” 120s timeout (webpack compilation)
  4. 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