AI Tools Compared

AI Tools for Automated Envoy Proxy Configuration

Envoy proxy configuration is notoriously verbose. A complete config for a simple service with TLS, retry policies, and rate limiting runs to hundreds of lines of YAML. AI tools can dramatically accelerate this — but they need to be guided carefully, because Envoy’s configuration schema is version-sensitive and the AI training data includes many outdated patterns.


What AI Is Good For

What to Verify Manually


Workflow 1: Generating a Basic Envoy Config

Prompt:

Generate an Envoy proxy static configuration (v3 API) for:
- Listener on port 8080
- Routes traffic to an upstream cluster at backend-service:9090
- Adds request timeout of 30 seconds
- Retries on 5xx errors up to 3 times
- Adds x-request-id header if not present

Claude’s output:

static_resources:
  listeners:
    - name: main_listener
      address:
        socket_address:
          address: 0.0.0.0
          port_value: 8080
      filter_chains:
        - filters:
            - name: envoy.filters.network.http_connection_manager
              typed_config:
                "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
                stat_prefix: ingress_http
                generate_request_id: true
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: backend
                      domains: ["*"]
                      routes:
                        - match:
                            prefix: "/"
                          route:
                            cluster: backend_cluster
                            timeout: 30s
                            retry_policy:
                              retry_on: "5xx"
                              num_retries: 3
                              per_try_timeout: 10s
                http_filters:
                  - name: envoy.filters.http.router
                    typed_config:
                      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

  clusters:
    - name: backend_cluster
      connect_timeout: 5s
      type: LOGICAL_DNS
      dns_lookup_family: V4_ONLY
      load_assignment:
        cluster_name: backend_cluster
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: backend-service
                      port_value: 9090

This is valid v3 API config. Validate with envoy --mode validate -c config.yaml before deploying.


Workflow 2: Adding Rate Limiting

Envoy’s local rate limiting filter is often simpler than the global rate limiting service for basic use cases.

Prompt:

Add a local rate limit to the Envoy config above:
- 100 requests per minute per IP address
- Return 429 with a Retry-After header when exceeded
- Exempt requests with the header X-Internal: true

Generated filter config:

http_filters:
  - name: envoy.filters.http.local_ratelimit
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.local_ratelimit.v3.LocalRateLimit
      stat_prefix: http_local_rate_limiter
      token_bucket:
        max_tokens: 100
        tokens_per_fill: 100
        fill_interval: 60s
      filter_enabled:
        runtime_key: local_rate_limit_enabled
        default_value:
          numerator: 100
          denominator: HUNDRED
      filter_enforced:
        runtime_key: local_rate_limit_enforced
        default_value:
          numerator: 100
          denominator: HUNDRED
      response_headers_to_add:
        - append_action: OVERWRITE_IF_EXISTS_OR_ADD
          header:
            key: x-local-rate-limit
            value: "true"
        - append_action: OVERWRITE_IF_EXISTS_OR_ADD
          header:
            key: Retry-After
            value: "60"
      status: 429

  - name: envoy.filters.http.router
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

Note: Per-IP rate limiting with local rate limit requires a descriptor-based approach. For true per-IP limiting, you need the global rate limit service or use a Lua filter. Claude correctly notes this limitation when asked — GPT-4 sometimes generates per-IP config that doesn’t actually work with the local rate limit filter.


Workflow 3: JWT Authentication Filter

Prompt:

Add JWT authentication to the Envoy config:
- Validate JWT tokens from Authorization: Bearer header
- JWKS endpoint: https://auth.example.com/.well-known/jwks.json
- Allow unauthenticated requests to /health and /metrics
- Forward the JWT payload as x-jwt-payload header to the upstream
http_filters:
  - name: envoy.filters.http.jwt_authn
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.jwt_authn.v3.JwtAuthentication
      providers:
        auth_provider:
          issuer: "https://auth.example.com"
          audiences:
            - "my-service"
          remote_jwks:
            http_uri:
              uri: "https://auth.example.com/.well-known/jwks.json"
              cluster: jwks_cluster
              timeout: 5s
            cache_duration: 300s
          forward_payload_header: x-jwt-payload
          payload_in_metadata: jwt_payload
      rules:
        - match:
            prefix: "/health"
        - match:
            prefix: "/metrics"
        - match:
            prefix: "/"
          requires:
            provider_name: auth_provider

  - name: envoy.filters.http.local_ratelimit
    # ... (rate limit config from above)

  - name: envoy.filters.http.router
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.filters.http.router.v3.Router

Add the JWKS cluster to your static resources:

- name: jwks_cluster
  connect_timeout: 5s
  type: LOGICAL_DNS
  load_assignment:
    cluster_name: jwks_cluster
    endpoints:
      - lb_endpoints:
          - endpoint:
              address:
                socket_address:
                  address: auth.example.com
                  port_value: 443
  transport_socket:
    name: envoy.transport_sockets.tls
    typed_config:
      "@type": type.googleapis.com/envoy.extensions.transport_sockets.tls.v3.UpstreamTlsContext
      sni: auth.example.com

Tool Comparison

Task Claude GPT-4 Copilot
v3 API syntax Accurate Occasionally uses deprecated v2 fields Limited — not enough context
Filter chain ordering Gets it right Sometimes puts router before other filters N/A
JWT auth config Correct, complete Usually correct Incomplete
Rate limiting Explains local vs global correctly Sometimes generates non-functional per-IP config N/A
xDS API resources Good understanding Decent Not useful
Explaining errors Clear Clear N/A
Lua filters Generates working Lua Good N/A

Copilot is largely unhelpful for Envoy configs — the configs are too specialized and context-heavy for inline completions. Use Claude or GPT-4 in chat mode.


Common Mistakes to Check

1. Filter ordering matters: JWT auth must come before the router filter. Rate limiting should also precede the router. Always verify the order in generated configs.

2. v2 vs v3 API: Configs using typed_config with type.googleapis.com/envoy.extensions.* are v3. If you see bare filter names without typed_config, that’s deprecated v2.

3. Cluster type:

4. Timeout semantics: timeout on the route is the global timeout. per_try_timeout is per retry attempt. Both matter for retry policy correctness.


Prompting Tips

Specify the Envoy version. Version 1.28+ has different filter names for some extensions than 1.24.

Include whether you’re running in Docker/Kubernetes or bare metal — affects how you reference clusters and listener addresses.

Ask for validation commands: envoy --mode validate -c /path/to/config.yaml

If you’re using Envoy as a sidecar with xDS (e.g., in Istio), tell the AI — the config structure is completely different from static configs.



Built by theluckystrike — More at zovo.one