System Design

API Gateway Patterns: Routing, Auth, Rate Limiting

Dive deep into API Gateway patterns: intelligent request routing, robust authentication, and critical rate limiting. Master modern API architecture for scalable, secure, and performant microservices.

Khader Vali July 12, 2026 14 min read

API Gateway Patterns: The Pillars of Modern API Architecture

In the ever-evolving landscape of distributed systems and microservices, the API Gateway stands as a crucial architectural component. It’s more than just a reverse proxy; it’s the sophisticated bouncer, traffic controller, and security guard for your entire backend ecosystem. For any senior engineer or technical architect, understanding the core patterns it enables—specifically request routing, authentication, and rate limiting—is not just beneficial, it’s essential for building scalable, secure, and resilient applications.

At Khadervali.com, we believe in demystifying complex technical topics. Today, we’ll dive deep into these fundamental API Gateway patterns, exploring their importance, implementation strategies, and real-world scenarios. By the end of this article, you’ll have a solid grasp of how to leverage an API Gateway to build robust and performant APIs.

API Gateway: The Unsung Hero of Modern Architectures

Before we dissect the patterns, let’s firmly establish what an API Gateway is and why it has become indispensable, especially in microservices architectures. An API Gateway is a server that acts as the single entry point for a set of microservices or backend services. It sits between the client applications (web, mobile, third-party) and the various backend services, handling requests and routing them to the appropriate service.

The “why” is manifold:

  • Abstraction and Decoupling: Clients no longer need to know the intricate topology of your backend services. They interact with a single, stable endpoint.
  • Centralized Concerns: Cross-cutting concerns like authentication, authorization, rate limiting, logging, and monitoring can be handled in one place, rather than duplicated across every microservice.
  • Reduced Client Complexity: Clients don’t need to manage multiple endpoints or implement complex logic for security and resilience.
  • Improved Performance and Scalability: Gateways can handle load balancing, caching, and request aggregation, offloading work from individual services and improving overall system responsiveness.
  • Enhanced Security: By acting as a perimeter, the Gateway can enforce security policies before requests even reach your core services.

Common implementations range from dedicated API Gateway products like Kong, Tyk, Apigee, and AWS API Gateway, to more general-purpose reverse proxies like Nginx or Envoy configured with specific logic. Regardless of the tool, the fundamental patterns remain consistent.

Imagine a typical request flow: A client (e.g., a web browser or mobile app) initiates a request targeting your API Gateway’s public endpoint. The API Gateway acts as the sole entry point. Upon receiving the request, the Gateway first applies its security and traffic management policies. It might validate an incoming authentication token, check an API key, or assess if the client has exceeded their allotted request quota. If any of these initial checks fail, the request is immediately rejected with an appropriate error response, preventing malicious or excessive traffic from reaching your backend services. If all initial checks pass, the Gateway then determines which specific backend microservice should handle the request based on pre-defined routing rules (e.g., URL path, HTTP headers). This often involves looking up a service in a service discovery registry. Finally, the Gateway forwards the request to the chosen backend service, potentially enriching the request with validated user information or other context. The backend service processes the request, sends its response back to the API Gateway, which then relays it efficiently to the original client.

This centralized control point offers immense power and flexibility, acting as the nervous system for your distributed applications.

API Gateway Patterns: Routing, Auth, Rate Limiting
Generated Image

Pattern 1: Intelligent Request Routing

Request routing is perhaps the most fundamental function of an API Gateway. It’s the mechanism that directs an incoming API request from a client to the correct backend service or endpoint. Without intelligent routing, a monolithic application would require a dedicated endpoint for every service, burdening clients with managing complex service locations. In a microservices world, where services can scale up and down, change network locations, or be deployed in different versions, robust routing is non-negotiable.

What is Request Routing?

At its core, request routing is about mapping an external API endpoint to an internal service endpoint. This mapping can be simple or incredibly sophisticated, driven by various factors in the incoming request. The importance of this pattern cannot be overstated:

  • Decoupling Clients from Service Topology: Clients only need to know the Gateway’s URL, not the IPs or hostnames of individual microservices. This allows backend services to evolve independently.
  • Load Balancing: Requests can be distributed across multiple instances of the same service to prevent overload and improve responsiveness.
  • A/B Testing and Canary Releases: A subset of users can be routed to a new version of a service, allowing for controlled testing and gradual rollouts.
  • Blue/Green Deployments: Traffic can be instantly switched between two identical environments (blue and green) for zero-downtime deployments.
  • Service Versioning: Different clients or API versions can be routed to different backend service versions.

Routing Strategies and Implementations

API Gateways employ various strategies to determine the destination of a request:

  • Path-based Routing: The most common strategy. The URL path is used to identify the target service.
    • /users/* routes to the User Service.
    • /products/* routes to the Product Service.
  • Host-based Routing: Requests are routed based on the hostname in the URL. Useful for multi-tenant applications or exposing different APIs on different subdomains.
    • api.example.com routes to the main API.
    • partner.example.com routes to the Partner API.
  • Header-based Routing: HTTP headers can contain routing metadata. This is particularly useful for canary releases or internal vs. external routing.
    • If `X-Version: v2` header is present, route to version 2 of a service.
    • If `X-Internal-User: true` header is present, route to an internal-only endpoint.
  • Query Parameter-based Routing: Similar to header-based, but uses query parameters. Less common for critical routing due to cacheability issues, but useful for specific testing scenarios.
    • /api/items?version=beta routes to a beta version of the Items service.
  • Weighted Routing: Traffic is distributed to different service instances based on pre-defined weights. Essential for canary deployments and gradual rollouts. For example, 90% of traffic to Service A v1 and 10% to Service A v2.
  • Service Discovery Integration: Modern API Gateways don’t hardcode service IP addresses. Instead, they integrate with service discovery mechanisms (e.g., Consul, Eureka, Kubernetes DNS) to dynamically find the current network location of a service instance. This is crucial in dynamic, cloud-native environments.

Architecture Description (in words)

When a client sends a request to the API Gateway, the Gateway performs several steps to route it:

  1. The Gateway receives the incoming HTTP request.
  2. It parses the request, extracting relevant information like the URL path, HTTP method, host header, and any other specified headers or query parameters that might influence routing.
  3. The Gateway then consults its internal routing configuration or policies. These rules define how different requests should be mapped to backend services.
  4. If the Gateway is integrated with a service discovery system (which is standard practice), it queries the registry to find healthy instances of the target backend service. This ensures requests are only sent to available and operational services.
  5. Based on the routing rules and service discovery results, the Gateway selects a specific instance of the target service (applying load balancing algorithms if multiple instances are available).
  6. Finally, the Gateway forwards the original request (potentially modifying headers or body) to the chosen backend service instance.
  7. Once the backend service processes the request and sends a response back to the Gateway, the Gateway relays this response back to the original client.

Code Example: Conceptual Gateway Routing Configuration (YAML)

Here’s a conceptual configuration snippet, inspired by tools like Kong Gateway or Nginx, demonstrating path-based and weighted routing:

# --- routes.yaml ---
# Define the routes for the API Gateway

routes:
  - name: user-service-api
    paths:
      - /api/v1/users
      - /api/v1/profiles
    methods: [GET, POST, PUT, DELETE]
    destinations:
      - host: user-service.internal
        port: 8080
        # Optional: load balancing policy (e.g., round-robin, least-connections)
        load_balancing: round-robin

  - name: product-service-api
    paths:
      - /api/v1/products
    methods: [GET, POST, PUT, DELETE]
    destinations:
      - host: product-service.internal
        port: 8081

  - name: payment-service-api-v1
    paths:
      - /api/v1/payments
    methods: [POST]
    destinations:
      - host: payment-service-v1.internal
        port: 8082
    # Apply header-based routing for specific payment types
    headers:
      X-Payment-Provider: [Stripe]

  - name: payment-service-api-v2-canary
    paths:
      - /api/v1/payments
    methods: [POST]
    destinations:
      - host: payment-service-v2.internal
        port: 8083
    # Weighted routing: 10% of traffic for A/B testing or canary release
    weight: 0.1
    # Specific header to force V2 for internal testing
    headers:
      X-Test-Version: [v2]
      
  - name: payment-service-api-v2-stable
    paths:
      - /api/v1/payments
    methods: [POST]
    destinations:
      - host: payment-service-v2.internal
        port: 8083
    # Weighted routing: 90% of traffic for V2 stable
    weight: 0.9
    
# Example of a rewrite rule
rewrites:
  - path: /old-api/widgets
    target: /api/v1/products
    method: GET
    
# Fallback route for unmatched requests
default_route:
  destinations:
    - host: error-handling-service.internal
      port: 8084

Real-world Scenario: Migrating a Monolith with Zero Downtime

Imagine your company is migrating a legacy monolithic application’s API to a new suite of microservices. The old API is at /api/legacy/*, and the new services will expose endpoints like /api/v1/users, /api/v1/products, etc. You need to perform this migration with zero downtime and minimal impact on existing clients.

An API Gateway makes this trivial. You can configure the Gateway to:

  1. Initially, route all /api/legacy/* requests to the monolithic application.
  2. As new microservices are ready (e.g., User Service at user-service.internal), you add new routing rules:
    # ... (other routes) ...
    routes:
      - name: legacy-api
        paths:
          - /api/legacy/*
        destinations:
          - host: monolith.internal
            port: 8080
    
      - name: new-user-api
        paths:
          - /api/v1/users/*
        destinations:
          - host: user-service.internal
            port: 8081
    
  3. For specific endpoints, you can use weighted routing. For instance, if you’re replacing /api/legacy/orders with /api/v1/orders, you can start by routing 5% of traffic to the new service, gradually increasing the weight as confidence grows.
    routes:
      - name: orders-legacy
        paths:
          - /api/legacy/orders
        destinations:
          - host: monolith.internal
            port: 8080
        weight: 0.95 # 95% of traffic still goes to legacy
    
      - name: orders-new
        paths:
          - /api/v1/orders
        destinations:
          - host: order-service.internal
            port: 8082
        weight: 0.05 # Start with 5% to the new service
    

This allows for a phased, controlled migration, reducing risk and ensuring a smooth transition for your users.

Pattern 2: Robust API Authentication and Authorization

Security is paramount for any public-facing API. The API Gateway serves as the first line of defense, centralizing authentication and often performing initial authorization checks before requests ever reach your backend services. This offloads a significant burden from individual microservices and ensures consistent security policies across your entire API surface.

The Security Imperative

Why handle authentication and authorization at the Gateway?

  • Centralized Security Policy Enforcement: Ensures that all incoming requests are authenticated according to a single, consistent policy, regardless of which backend service they target.
  • Reduced Service Complexity: Individual microservices can focus on their business logic, trusting that the Gateway has handled the initial security checks. This adheres to the single responsibility principle.
  • Protection for Backend Services: Unauthenticated or unauthorized requests are rejected at the edge, preventing them from consuming backend resources or exposing vulnerabilities.
  • Easier Auditing and Logging: All security events (successful authentications, failed attempts) can be logged in one place.
  • Support for Multiple Authentication Schemes: The Gateway can support various authentication methods (API Keys, OAuth, JWTs) and translate them into a consistent internal format for backend services.

It’s important to distinguish between authentication (verifying the identity of a client or user – “who are you?”) and authorization (determining what an authenticated client/user is allowed to do – “what can you do?”). The API Gateway typically handles authentication and coarse-grained authorization (e.g., “is this user allowed to access any part of the ‘admin’ API?”). Fine-grained authorization (e.g., “can this user view *this specific* order?”) is usually left to the individual microservices, as it requires deeper domain knowledge.

Authentication Mechanisms at the Gateway

API Gateways support various authentication methods:

  • API Keys: A simple, static token passed in a header (e.g., X-API-Key) or query parameter. The Gateway validates this key against a store (database, cache). While easy to implement, API keys are less secure than token-based approaches due to their static nature and lack of expiry.
  • OAuth 2.0 / OpenID Connect (OIDC): The industry standard for secure, token-based authentication and authorization.
    • JSON Web Tokens (JWTs): A compact, URL-safe means of representing claims to be transferred between two parties. JWTs are typically issued by an Identity Provider (IdP) after a user authenticates. The API Gateway validates these JWTs by checking their signature (using a public key from the IdP), expiry, issuer, and audience.
    • Upon successful validation, the Gateway can extract claims (user ID, roles, scopes) from the JWT and inject them into request headers (e.g., X-User-ID, X-User-Roles) before forwarding the request to the backend services.
  • Mutual TLS (mTLS): A robust security mechanism where both the client and the server verify each other’s digital certificates. This provides strong identity verification for both ends of the connection and encrypts traffic. It’s often used for sensitive service-to-service communication or for high-security client applications.
  • Basic Authentication: Username and password sent in the Authorization header (encoded in Base64). While widely supported, it’s generally considered less secure for modern APIs unless upgraded to token-based security by the Gateway.

Architecture Description (in words)

Let’s trace a request through the authentication process at the Gateway:

  1. A client application initiates a request, including an authentication credential (e.g., a JWT in the Authorization: Bearer header, or an API Key in X-API-Key).
  2. The API Gateway intercepts this request as its first processing step (even before routing in many designs).
  3. The Gateway’s authentication policy module examines the credential.
    • If it’s an API Key, the Gateway queries its internal key store or a database to verify the key’s existence and validity.
    • If it’s a JWT, the Gateway performs several checks:
      • Signature Verification: It uses the public key of the Identity Provider (obtained from a JWKS endpoint) to verify that the token’s signature is valid and hasn’t been tampered with.
      • Expiry Check: Ensures the token has not expired.
      • Issuer and Audience Validation: Confirms the token was issued by a trusted IdP and is intended for this API.
  4. If the credential is invalid (e.g., expired token, unknown API key, invalid signature), the Gateway immediately rejects the request with a 401 Unauthorized or 403 Forbidden HTTP status code, preventing any further processing and protecting backend services.
  5. If the credential is valid, the Gateway extracts relevant user or client information (e.g., user ID, roles, scopes, client ID) from the validated token or API key.
  6. This extracted information is then typically added as new HTTP headers (e.g., X-Authenticated-User-ID, X-User-Roles) to the request before it’s forwarded to the backend service. This allows backend services to perform fine-grained authorization without re-authenticating the user.

Code Example: Conceptual Gateway JWT Authentication Policy (JSON)

This example illustrates how a gateway might be configured to validate JWTs. This is often done via plugins or built-in policies in commercial gateways.

{
  "authentication": {
    "jwt_validation": {
      "enabled": true,
      "issuer": "https://your-idp.auth0.com/",
      "audience": "your-api-audience",
      "jwks_uri": "https://your-idp.auth0.com/.well-known/jwks.json",
      "signature_algorithm": ["RS256", "ES256"],
      "token_header": "Authorization",
      "token_prefix": "Bearer ",
      "claims_to_headers": {
        "sub": "X-User-ID",
        "roles": "X-User-Roles",
        "scope": "X-User-Scopes"
      },
      "allow_anonymous": false,
      "error_message": "Invalid or expired authentication token."
    },
    "api_key_validation": {
      "enabled": true,
      "key_header": "X-API-Key",
      "key_source": {
        "type": "database",
        "connection_string": "postgres://user:pass@db:5432/gateway_keys"
      },
      "error_message": "Invalid API Key."
    }
  },
  "authorization_rules": [
    {
      "path_prefix": "/admin/*",
      "required_claims": {
        "roles": ["admin"]
      },
      "reject_status": 403,
      "reject_message": "Access Denied: Admin privileges required."
    },
    {
      "path_prefix": "/api/v1/orders",
      "method": "POST",
      "required_scopes": ["write:orders"],
      "reject_status": 403,
      "reject_message": "Access Denied: Missing 'write:orders' scope."
    }
  ]
}

Real-world Scenario: Securing a Multi-Client API

Consider an e-commerce platform with a public API accessed by:

  • A single-page web application (SPA)
  • A mobile application
  • Partner integrations (e.g., shipping providers, payment gateways)

Each client type has different authentication needs and access levels.

  • The SPA and mobile app use OAuth 2.0/OIDC. Users log in, receive JWTs, and the Gateway validates these tokens. The Gateway extracts the user_id and roles from the JWT and passes them to backend services.
  • Partner integrations use API Keys for server-to-server communication. The Gateway verifies the API Key against a secure store, potentially mapping it to a specific partner ID and a set of allowed scopes.

The Gateway can enforce that only authenticated users/partners can access certain endpoints. For instance, any request to /api/v1/admin/* might require a JWT with an admin role claim, while /api/v1/products might only require a valid API key or a user JWT with a read:products scope. This centralized approach simplifies security management immensely compared to implementing these checks in every microservice.

API Gateway Patterns: Routing, Auth, Rate Limiting
Generated Image

Pattern 3: Intelligent Rate Limiting

Rate limiting is a critical control mechanism implemented at the API Gateway to manage the volume of requests a client can make within a given time frame. It’s an indispensable tool for protecting your backend services from various forms of abuse, ensuring fair usage, and maintaining the stability and performance of your entire system.

Why Rate Limiting is Crucial

Implementing rate limiting at the Gateway provides several

Written by

Khader Vali

Senior Software Engineer specializing in cloud architecture, real-time systems, and enterprise-scale applications.

Share this article

Related Articles

Designing Event-Driven Microservices: A Practical Guide

Jul 22, 2026 · 16 min read

CQRS and Event Sourcing pattern for scalable application design

CQRS & Event Sourcing: Scalable, Resilient Apps

May 29, 2026 · 6 min read

Strangler Fig Pattern: Safe Monolith to Microservices Migration

Jul 05, 2026 · 19 min read