API Gateway Patterns skill for Codex

A thin edge that never turns into a monolith. Codex chooses between a plain proxy, a shared gateway, per-client BFFs and a GraphQL layer, then puts TLS, token validation, header stripping, rate limits and request IDs at the edge while keeping authorization and business rules in services. BFF aggregation calls upstreams in parallel with per-call timeouts and returns partial data when optional services fail. Gateway config changes are diffed and confirmed before they hit shared environments.

  • Architecture
  • $api-gateway-patterns
  • 199 lines
  • 2 files
  • ~2,250 tokens
  • MIT
  • Updated

Install

curl -fsSL codexskills.dev/install.sh \  | sh -s -- api-gateway-patterns

Installs to ~/.agents/skills/api-gateway-patterns/ for every project on this machine.

104-line POSIX script. No sudo, no telemetry. Read install.sh

Use it in Codex

Start a prompt with $api-gateway-patterns, or pick it from /skills. You can also just describe the task: Codex reads the description below and loads the playbook when your request matches.

What Codex reads before loading it

Designs the edge of a service-based system - single API gateway, backend-for-frontend (BFF) per client, or GraphQL layer - deciding what belongs at the gateway (TLS, token validation, rate limits, routing, request IDs, size limits) and what must stay in services (authorization, business rules), plus response aggregation with timeouts and partial failure, using Kong, Envoy, the Kubernetes Gateway API, AWS API Gateway or a custom BFF. Use when adding a gateway or BFF, offloading auth, combining several service calls for a client screen, or reviewing a gateway that has grown business logic.

Use it when

  • Adding a gateway or backend-for-frontend in front of several services
  • Offloading authentication, rate limiting or CORS to the edge
  • A client screen needs data from several services in one response
  • A gateway has accumulated business logic or fragile transformations

Use something else when

  • You are configuring Amazon API Gateway resources specifically: use aws-api-gateway
  • You are designing the API contract itself rather than the edge: use api-design-review
  • You need per-client rate-limit algorithms and headers in depth: use api-rate-limiting

How to check the result

A forged identity header with another user's valid token reaches the backend only as the verified identity, bad tokens get 401 at the edge, and a slowed optional upstream yields a degraded response within budget.

The mistake it prevents

Forwarding client-supplied X-User-Id style headers unchanged, letting any caller impersonate another user once auth is offloaded to the gateway.

~/.agents/skills/api-gateway-patterns/SKILL.md

--- name: api-gateway-patterns description: Designs the edge of a service-based system - single API gateway, backend-for-frontend (BFF) per client, or GraphQL layer - deciding what belongs at… license: MIT ---

A well-designed edge gives clients one stable entry point, rejects bad traffic before it reaches services, and composes responses without becoming a second monolith. The tests: the gateway holds no business rules, a slow backend degrades one part of a response instead of the whole page, and services still enforce authorization on their own data.

Pick the edge shape

ShapeUse whenWatch out for
Reverse proxy / load balancer onlyOne backend or a modular monolithNothing more needed; do not add a gateway for its own sake
Single API gatewaySeveral services, one public API, cross-cutting concerns to centraliseBecoming the place every team edits; keep it config, not code
BFF per client (web, mobile, partner)Clients need different shapes, payload sizes or release cadenceDuplicated logic across BFFs; each BFF owned by its client team
GraphQL gateway / federationMany clients composing data from many services flexiblyQuery cost limits, N+1 to backends, schema ownership ($graphql-federation)
Service meshEast-west (service-to-service) mTLS, retries, telemetryNot a replacement for the north-south gateway

Common combination: managed or Kubernetes gateway at the edge for TLS, auth and limits, then a thin BFF per client for aggregation.

What belongs where

ConcernGatewayService
TLS termination, HTTP/2, compressionYes-
Token validation (signature, expiry, audience, issuer)YesRe-validate, or trust only gateway-authenticated mTLS traffic
Authorization on resources (“may user 7 read order 812?”)NoYes, always
Coarse access (route requires scope orders:read)YesOptional second check
Rate limiting, quotas per API key or tenantYesService-level protection (concurrency limits) too
Request size limits, header limits, method allow-listsYes-
Request ID / trace context injectionYesPropagate
CORSYes, in one place-
Routing, canary weights, versioned pathsYes-
Response caching of public GETsYes, with correct Cache-ControlSet the headers
Validation of business input, pricing, workflowNoYes
Aggregating several services for one screenBFF, not the shared gateway-

Auth offload done safely

  1. Clients send Authorization: Bearer <JWT> (or a session cookie to a BFF, which holds tokens server-side).
  2. The gateway validates signature against the issuer’s JWKS (cached), exp, nbf, iss and aud. Reject on failure with 401.
  3. The gateway strips any incoming identity headers (X-User-Id, X-Tenant-Id) from the client request, then sets them from verified claims. Otherwise a client can spoof identity by sending the header itself.
  4. Services accept identity headers only from the gateway: enforce with mTLS or network policy, or forward the original JWT and have services verify it themselves.
  5. Services make the authorization decision on the resource.

For browser clients, prefer a BFF with an httpOnly, Secure, SameSite session cookie over storing tokens in JavaScript; the BFF attaches tokens server-side.

Configuration examples

Kubernetes Gateway API (portable across Envoy Gateway, Istio, NGINX Gateway Fabric, cloud implementations):

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: orders
spec:
  parentRefs:
    - name: public-gateway
  hostnames: ["api.example.com"]
  rules:
    - matches:
        - path: { type: PathPrefix, value: /v1/orders }
      backendRefs:
        - name: orders
          port: 8080
          weight: 90
        - name: orders-canary
          port: 8080
          weight: 10

Auth, rate limiting and timeouts are implementation-specific policies attached to routes (for example Envoy Gateway SecurityPolicy and BackendTrafficPolicy); read the chosen implementation’s docs rather than assuming field names.

Kong declarative config (decK) for edge concerns:

_format_version: "3.0"
services:
  - name: orders
    url: http://orders.internal:8080
    connect_timeout: 2000
    read_timeout: 5000
    routes:
      - name: orders
        paths: ["/v1/orders"]
        strip_path: false
    plugins:
      - name: rate-limiting
        config: { minute: 600, policy: local, limit_by: consumer }
      - name: request-size-limiting
        config: { allowed_payload_size: 2 }
      - name: correlation-id
        config: { header_name: X-Request-ID, generator: uuid, echo_downstream: true }

Applying gateway config to a shared or production environment changes live traffic: show the diff (deck gateway diff, kubectl diff) and get explicit confirmation first.

Aggregation in a BFF

Call independent backends in parallel, give each a timeout below the client’s budget, and return partial data with an explicit marker instead of failing the whole screen.

// BFF handler for the order details screen (Node 20+, global fetch)
export async function orderScreen(orderId: string, auth: string) {
  const call = (url: string, ms: number) =>
    fetch(url, { headers: { authorization: auth }, signal: AbortSignal.timeout(ms) })
      .then((r) => (r.ok ? r.json() : Promise.reject(new Error(`${url} -> ${r.status}`))));

  const [order, shipment, recs] = await Promise.allSettled([
    call(`http://orders/v1/orders/${orderId}`, 800),        // required
    call(`http://shipping/v1/shipments?order=${orderId}`, 600),
    call(`http://recs/v1/for-order/${orderId}`, 300),       // nice to have
  ]);

  if (order.status === "rejected") throw new UpstreamError("orders", order.reason);
  return {
    order: order.value,
    shipment: shipment.status === "fulfilled" ? shipment.value : null,
    recommendations: recs.status === "fulfilled" ? recs.value : [],
    degraded: [shipment, recs].some((r) => r.status === "rejected"),
  };
}

Rules for aggregation:

  • Classify each upstream as required or optional; only required failures fail the response.
  • Timeouts: total client budget minus margin, then per-call budgets below it. No upstream call without a timeout.
  • No retries at the BFF for non-idempotent calls; for idempotent GETs at most one retry within the budget.
  • Avoid sequential dependent calls where a backend can return the needed data directly.
  • Keep transformation to shaping and renaming; if a rule decides something about the business, it belongs in a service.

Workflow

- [ ] 1. Read AGENTS.md and existing ingress/gateway config; list clients and services
- [ ] 2. Choose the edge shape (table above); record an ADR if introducing a new layer
- [ ] 3. Assign concerns to gateway vs service (table above) and remove misplaced logic
- [ ] 4. Configure auth validation, header stripping, rate limits, size limits, request IDs
- [ ] 5. Build BFF aggregation with per-call timeouts and partial responses
- [ ] 6. Add metrics per route (rate, errors, p99) and upstream timeout counters
- [ ] 7. Diff and confirm before applying gateway config to shared environments

Gotchas

  • The gateway as an ESB: transformation scripts, business validation and orchestration in Lua or policy XML nobody tests. Move logic into services or a BFF with tests.
  • One shared BFF for all clients becomes a general-purpose gateway again. One BFF per client experience, owned by that client’s team.
  • Gateway timeouts shorter than backend timeouts cause work to continue after the client gave up; align them so each layer’s timeout is shorter than its caller’s.
  • Rate limiting per IP behind a CDN limits the CDN; key on API key, user or tenant, and configure trusted proxy headers correctly.
  • Gateways that retry POSTs duplicate side effects. Retry only idempotent methods or requests with idempotency keys ($idempotency-keys).
  • A single gateway is a single point of failure and a shared blast radius; run it replicated across zones and roll out config changes gradually.

Verification

  • Send a request with a forged X-User-Id header and a valid token for another user: the backend must see the verified identity only.
  • Expired, wrong-audience and wrong-issuer tokens get 401 at the gateway.
  • Slow one optional upstream (fault injection or a stub with delay): the BFF returns within budget with degraded: true.
  • Rate limit returns 429 with Retry-After at the configured threshold for one key, and does not affect other keys.

Output contract

**Edge shape:** <gateway | gateway + BFFs | GraphQL> (ADR-00xx)
**Gateway concerns:** TLS, JWT validation (iss/aud), header stripping, rate limits <values>, size limit <value>, request IDs
**Moved out of gateway:** <logic moved to services/BFF>
**BFF endpoints:** <route -> upstreams (required/optional), budgets>
**Verification:** spoofed header test, token tests, degraded-mode test, 429 test

What the zip contains

SKILL.md plus the interface file below. Nothing runs on install.

agents/openai.yamlgenerated from this page

Gives the Codex app a display name, a one-line description and a starter prompt for this skill.

interface:
  display_name: "API Gateway Patterns"
  short_description: "A thin edge that never turns into a monolith"
  default_prompt: "$api-gateway-patterns Design a BFF for our mobile app that combines orders, shipping and recommendations"

About this skill

Written and maintained by the Codex Skills editors to the same editorial standard as every skill here: a selective description, a real workflow, known pitfalls and a way to verify the work. First published , last updated . MIT licensed. Something wrong or out of date? Tell us.

esc
Just launched

Codex Skills Pro is live

79 premium skills for Codex, each with scripts, references and an evidence report that proves the result.

Bought one by one$882.21
All 79 skills$49
94% off

That's $0.62 a skill, paid once.

Get all 79 for $49Or pick single skills from $4.99 →

Secure checkout by Creem