AI Tools Compared

AI-Powered API Gateway Configuration Tools 2026

API gateway configuration is high-stakes and verbose. A single misconfigured rate limit or missing auth plugin can expose services or break traffic. AI tools can accelerate the work, but you need to know where they’re reliable and where they hallucinate.

The Platforms

This guide covers three common gateway targets:

Kong Declarative Config

Prompt to Claude:

Write a Kong deck YAML configuration for a service called "orders-api" at http://orders-service:8080.
Routes: GET /orders, POST /orders, GET /orders/{id}.
Plugins: rate-limiting (100 req/min per consumer), key-auth, request-transformer to add header X-Gateway: kong.

Claude output:

_format_version: "3.0"
_transform: true

services:
  - name: orders-api
    url: http://orders-service:8080
    routes:
      - name: list-orders
        methods: [GET]
        paths: [/orders]
      - name: create-order
        methods: [POST]
        paths: [/orders]
      - name: get-order
        methods: [GET]
        paths: [~/orders/(?P<id>[^/]+)$]

    plugins:
      - name: key-auth
        config:
          key_names:
            - apikey
          hide_credentials: true

      - name: rate-limiting
        config:
          minute: 100
          policy: local
          limit_by: consumer

      - name: request-transformer
        config:
          add:
            headers:
              - "X-Gateway:kong"

This is correct deck v3 format. Claude gets the regex route syntax right (~/orders/(?P<id>...)), uses limit_by: consumer for per-consumer rate limiting, and sets hide_credentials: true on key-auth. GPT-4o often uses the older deck v1 format with a services: root that lacks _transform.

AWS API Gateway with Lambda Integration

Prompt:

Generate an AWS API Gateway OpenAPI 3.0 spec with API Gateway extensions for a POST /webhook endpoint.
Lambda integration: arn:aws:lambda:us-east-1:123456789012:function:WebhookHandler.
Add an API key requirement. Include CORS for https://app.example.com. Use proxy integration.

Claude output:

openapi: "3.0.1"
info:
  title: WebhookAPI
  version: "1.0"
x-amazon-apigateway-api-key-source: HEADER

paths:
  /webhook:
    post:
      operationId: receiveWebhook
      security:
        - ApiKeyAuth: []
      parameters: []
      requestBody:
        required: true
        content:
          application/json:
            schema:
              type: object
      responses:
        "200":
          description: OK
          headers:
            Access-Control-Allow-Origin:
              schema:
                type: string
      x-amazon-apigateway-integration:
        type: aws_proxy
        httpMethod: POST
        uri: arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:123456789012:function:WebhookHandler/invocations
        passthroughBehavior: when_no_match

    options:
      responses:
        "200":
          description: CORS preflight
          headers:
            Access-Control-Allow-Headers:
              schema:
                type: string
            Access-Control-Allow-Methods:
              schema:
                type: string
            Access-Control-Allow-Origin:
              schema:
                type: string
      x-amazon-apigateway-integration:
        type: mock
        requestTemplates:
          application/json: '{"statusCode": 200}'
        responses:
          default:
            statusCode: "200"
            responseParameters:
              method.response.header.Access-Control-Allow-Headers: "'Content-Type,X-Api-Key'"
              method.response.header.Access-Control-Allow-Methods: "'POST,OPTIONS'"
              method.response.header.Access-Control-Allow-Origin: "'https://app.example.com'"

components:
  securitySchemes:
    ApiKeyAuth:
      type: apiKey
      name: x-api-key
      in: header

Claude handles the AWS-specific x-amazon-apigateway-integration extension correctly. The mock integration for the CORS preflight OPTIONS handler with responseParameters is accurate — this is a common pain point that GPT-4o frequently gets wrong, omitting the responseParameters or using incorrect response mapping syntax.

Nginx as API Gateway

Prompt:

Write an Nginx config that acts as an API gateway for two upstream services:
- /api/users → user-service:3001
- /api/orders → order-service:3002
Add: rate limiting (20 req/s burst 40), JWT validation via auth_request to http://auth-service/validate,
upstream health checks, and gzip for JSON responses.

Claude output:

upstream user_service {
    server user-service:3001;
    keepalive 32;
}

upstream order_service {
    server order-service:3002;
    keepalive 32;
}

upstream auth_service {
    server auth-service:80;
    keepalive 16;
}

limit_req_zone $binary_remote_addr zone=api_limit:10m rate=20r/s;

server {
    listen 80;
    server_name api.example.com;

    gzip on;
    gzip_types application/json;
    gzip_min_length 1024;

    location = /auth/validate {
        internal;
        proxy_pass http://auth_service/validate;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
        proxy_set_header X-Original-Method $request_method;
        proxy_set_header Authorization $http_authorization;
    }

    location /api/users {
        limit_req zone=api_limit burst=40 nodelay;
        auth_request /auth/validate;
        auth_request_set $auth_status $upstream_status;

        proxy_pass http://user_service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }

    location /api/orders {
        limit_req zone=api_limit burst=40 nodelay;
        auth_request /auth/validate;
        auth_request_set $auth_status $upstream_status;

        proxy_pass http://order_service;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_http_version 1.1;
        proxy_set_header Connection "";
    }
}

This is solid production-level Nginx config. Claude correctly marks the auth location as internal, passes Authorization header to the auth service, sets proxy_pass_request_body off for the auth subrequest, and uses HTTP/1.1 with keepalive for upstream connections.

Where AI Tools Fall Short

All three tools have gaps:

For mTLS and VTL templates, treat AI output as a starting point and validate against the official docs.

Request/Response Transformation

Ask Claude to generate transformation rules that modify requests before sending to upstreams:

Prompt (Kong):

Write a Kong configuration that transforms POST requests to /api/webhook.
Add X-Timestamp header with current UTC time.
Remove X-Internal-ID header if present (security).
Add X-Gateway-Region header with value "us-west-2".

Claude produces:

plugins:
  - name: request-transformer
    config:
      add:
        headers:
          - "X-Timestamp:$(date -u +'%s')"
          - "X-Gateway-Region:us-west-2"
      remove:
        headers:
          - X-Internal-ID

This is correct Kong syntax. The $(date ...) template may not work in all Kong versions—Claude will acknowledge this if you ask for version compatibility.

Circuit Breaker Patterns

For resilience, ask Claude to generate circuit breaker configurations:

Prompt (Nginx):

Configure Nginx to implement circuit breaker behavior:
If upstream service returns 500+ status or times out 3 times in 30 seconds,
stop sending requests for 60 seconds. Log circuit breaker trips.

Claude generates:

# Requires nginx with additional modules
upstream service_backend {
    server backend:3000;
    keepalive 32;
}

# Track failure rate
limit_req_zone $binary_remote_addr zone=breaker:10m rate=10r/s;

server {
    location /api {
        # Attempt with timeout and error handling
        proxy_pass http://service_backend;
        proxy_connect_timeout 2s;
        proxy_read_timeout 5s;

        # Log errors for circuit breaker monitoring
        error_log /var/log/nginx/circuit_break.log warn;
        access_log /var/log/nginx/access.log combined;

        # Fallback for circuit breaker state
        error_page 502 503 504 = @circuit_open;
    }

    location @circuit_open {
        default_type application/json;
        return 503 '{"error":"Service temporarily unavailable"}';
    }
}

Note: Pure Nginx doesn’t have stateful circuit breaker — you’d use Kong or another gateway for true circuit breaking. Claude will note this if you ask.

Rate Limiting with Sliding Windows

Ask Claude for sophisticated rate limiting:

Kong rate-limiting that uses sliding window (not fixed buckets).
Limit: 1000 requests per hour per API key.
If limit reached, return 429 with Retry-After header.

Claude produces:

plugins:
  - name: rate-limiting
    config:
      minute: null
      hour: 1000
      policy: sliding
      limit_by: credential
      headers_retrieve_count: true
      error_code: 429
      sync_rate: -1  # synchronous rate limiting

  - name: response-transformer
    config:
      add:
        headers:
          - "Retry-After: 3600"

The policy: sliding ensures fair limiting even with bursts, and Retry-After tells clients when to retry.

Canary Deployments via Gateway

Ask Claude to generate canary deployment configs:

Write Nginx config that routes 10% of traffic to a new service version
and 90% to the stable version. Include A/B test header forwarding.

Claude generates:

upstream stable {
    server backend-stable:3000;
}

upstream canary {
    server backend-canary:3000;
}

# Split traffic: 10 canary, 90 stable
split_clients $request_id $backend {
    10% "canary";
    *   "stable";
}

server {
    location /api {
        # Add header to track which version served the request
        add_header X-Served-By $backend always;
        proxy_pass http://$backend;
    }
}

This enables gradual rollouts without modifying application code. Combined with monitoring on X-Served-By, you can detect issues in the canary early.

Security: API Key Validation

Ask Claude for secure API key handling:

Kong configuration that validates API keys from a custom backend service.
If validation fails, return 401. Log all key validation attempts (but not the key value).

Claude produces:

plugins:
  - name: request-termination
    config:
      status_code: 401
      message: "Unauthorized"
      condition:
        compare: request.headers['X-API-Key'] == nil

  - name: pre-function
    config:
      access:
        - |
          local api_key = ngx.var.http_x_api_key
          -- Log without exposing the key
          ngx.log(ngx.WARN, "API auth attempt: key_prefix=" .. string.sub(api_key, 1, 8))

This pattern validates before upstream processing and logs safely without exposing secrets.

Comparison: Rate Limiting Features

Gateway Sliding Window Per-Client Per-IP Headers
Kong Yes Yes Yes Excellent
Nginx Fixed bucket Limited Yes Manual
AWS API Gateway Token bucket Via API key Via Stage/Plan Good

Claude generates correct configs for all three but Kong is most flexible for complex policies.


AI-Powered API Gateway Configuration Tools 2026

API gateway configuration is one of those tasks that looks straightforward until you’re staring at a 400-line Kong declarative config trying to figure out why your rate limiting plugin is silently dropping requests. AI tools have gotten genuinely good at generating gateway configs — but they vary significantly in whether they understand the runtime behavior, not just the schema.

What Makes Gateway Config Generation Hard

The difficulty isn’t syntax. It’s behavior. A gateway config encodes security policy, traffic shaping, authentication chains, and transform logic. Mistakes are often silent — a misconfigured JWT plugin that accepts expired tokens, a rate limit that resets per-node instead of globally, a path rewrite that strips query parameters. AI tools that only know the YAML schema produce syntactically valid configs that behave incorrectly in production.

The better tools understand:

Claude for Kong Declarative Config

Prompt:

Generate a Kong declarative config (deck format) for an API gateway with:
- Two services: users-service (upstream: http://users:8080) and orders-service (upstream: http://orders:8080)
- Route /api/users/* to users-service, /api/orders/* to orders-service
- JWT authentication on both routes (HS256, secret from env)
- Rate limiting: 100 req/min per consumer globally (not per node), 1000 req/min service-wide
- Request logging plugin on both routes
- CORS enabled for https://app.example.com

Claude output:

_format_version: "3.0"
_transform: true

services:
  - name: users-service
    url: http://users:8080
    plugins:
      - name: rate-limiting
        config:
          minute: 1000
          policy: redis
          redis_host: redis
          redis_port: 6379
    routes:
      - name: users-route
        paths:
          - /api/users
        strip_path: false
        plugins:
          - name: jwt
            config:
              secret_is_base64: false
              claims_to_verify:
                - exp
              key_claim_name: iss
          - name: rate-limiting
            config:
              minute: 100
              policy: redis
              redis_host: redis
              redis_port: 6379
              limit_by: consumer
          - name: cors
            config:
              origins:
                - https://app.example.com
              methods:
                - GET
                - POST
                - PUT
                - DELETE
                - OPTIONS
              headers:
                - Authorization
                - Content-Type
              exposed_headers:
                - X-Request-Id
              max_age: 3600
          - name: http-log
            config:
              http_endpoint: http://logger:9000/logs
              method: POST
              timeout: 1000
              keepalive: 1000

  - name: orders-service
    url: http://orders:8080
    plugins:
      - name: rate-limiting
        config:
          minute: 1000
          policy: redis
          redis_host: redis
          redis_port: 6379
    routes:
      - name: orders-route
        paths:
          - /api/orders
        strip_path: false
        plugins:
          - name: jwt
            config:
              secret_is_base64: false
              claims_to_verify:
                - exp
              key_claim_name: iss
          - name: rate-limiting
            config:
              minute: 100
              policy: redis
              redis_host: redis
              redis_port: 6379
              limit_by: consumer
          - name: cors
            config:
              origins:
                - https://app.example.com
              methods:
                - GET
                - POST
                - PUT
                - DELETE
                - OPTIONS
              headers:
                - Authorization
                - Content-Type
              max_age: 3600
          - name: http-log
            config:
              http_endpoint: http://logger:9000/logs
              method: POST
              timeout: 1000
              keepalive: 1000

Claude correctly uses policy: redis for global (cross-node) rate limiting — the default policy: local resets per Kong node, which silently breaks rate limits in multi-instance deployments. It also applies the service-wide limit at the service level and the per-consumer limit at the route level, which is the correct separation.

AWS API Gateway Terraform

For AWS API Gateway v2 (HTTP API), Claude generates correct Terraform including the often-missed authorizer integration:

Prompt:

Terraform for AWS API Gateway v2 HTTP API. Routes: GET /users/{id} and POST /orders.
JWT authorizer using a Cognito user pool. Lambda integrations for each route.
Enable access logging to CloudWatch. Stage: prod.

Claude output (abbreviated):

resource "aws_apigatewayv2_api" "main" {
  name          = "main-api"
  protocol_type = "HTTP"
  cors_configuration {
    allow_origins = ["https://app.example.com"]
    allow_methods = ["GET", "POST", "OPTIONS"]
    allow_headers = ["Authorization", "Content-Type"]
    max_age       = 300
  }
}

resource "aws_apigatewayv2_authorizer" "cognito" {
  api_id           = aws_apigatewayv2_api.main.id
  authorizer_type  = "JWT"
  identity_sources = ["$request.header.Authorization"]
  name             = "cognito-authorizer"

  jwt_configuration {
    audience = [aws_cognito_user_pool_client.app.id]
    issuer   = "https://cognito-idp.${var.aws_region}.amazonaws.com/${aws_cognito_user_pool.main.id}"
  }
}

resource "aws_apigatewayv2_route" "get_user" {
  api_id             = aws_apigatewayv2_api.main.id
  route_key          = "GET /users/{id}"
  target             = "integrations/${aws_apigatewayv2_integration.users.id}"
  authorization_type = "JWT"
  authorizer_id      = aws_apigatewayv2_authorizer.cognito.id
}

resource "aws_apigatewayv2_stage" "prod" {
  api_id      = aws_apigatewayv2_api.main.id
  name        = "prod"
  auto_deploy = true

  access_log_settings {
    destination_arn = aws_cloudwatch_log_group.api_gw.arn
    format = jsonencode({
      requestId      = "$context.requestId"
      sourceIp       = "$context.identity.sourceIp"
      requestTime    = "$context.requestTime"
      protocol       = "$context.protocol"
      httpMethod     = "$context.httpMethod"
      resourcePath   = "$context.resourcePath"
      routeKey       = "$context.routeKey"
      status         = "$context.status"
      responseLength = "$context.responseLength"
      integrationErrorMessage = "$context.integrationErrorMessage"
    })
  }
}

Nginx Rate Limiting and Auth

For Nginx-based gateways, Claude handles the limit_req_zone / limit_req pattern and integrates with auth_request for external authentication:

# Rate limiting zones — defined in http block
limit_req_zone $binary_remote_addr zone=per_ip:10m rate=30r/m;
limit_req_zone $http_authorization zone=per_token:10m rate=100r/m;

server {
    listen 443 ssl http2;
    server_name api.example.com;

    # External auth check
    location = /auth {
        internal;
        proxy_pass http://auth-service:8080/validate;
        proxy_pass_request_body off;
        proxy_set_header Content-Length "";
        proxy_set_header X-Original-URI $request_uri;
        proxy_set_header Authorization $http_authorization;
    }

    location /api/users/ {
        auth_request /auth;
        auth_request_set $auth_status $upstream_status;

        limit_req zone=per_ip burst=5 nodelay;
        limit_req zone=per_token burst=20 nodelay;
        limit_req_status 429;

        proxy_pass http://users-service:8080/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

Troubleshooting Common AI-Generated Gateway Config Issues

Rate limits appear to not work: AI tools default to policy: local in Kong. For a cluster, this means limits reset per node. Always specify policy: redis and provide the Redis connection details.

JWT validation passes expired tokens: The claims_to_verify: [exp] must be explicitly set. Claude includes this; ChatGPT often omits it when the prompt doesn’t specifically mention token expiry.

CORS preflight fails: OPTIONS requests must be handled before auth plugins run. In Kong, add config.preflight_continue: false to the CORS plugin. In Nginx, handle OPTIONS before the auth_request directive.

Path stripping breaks downstream services: Kong’s strip_path: true removes the matched path prefix. If /api/users/123 should reach the upstream as /users/123, set strip_path: true. If it should arrive as /api/users/123, set strip_path: false. Claude gets this right when you specify; ChatGPT defaults to stripping.

Built by theluckystrike — More at zovo.one