System Design

API Gateway Patterns: Routing, Auth, Rate Limiting Explained

Master API Gateway patterns: request routing, centralized authentication, and intelligent rate limiting. Learn architecture, code, and real-world scenarios for robust microservices.

Khader Vali August 12, 2026 7 min read

Mastering API Gateway Patterns: Routing, Authentication, and Rate Limiting

As microservices architectures become the de facto standard for building scalable, resilient, and independently deployable applications, the need for a robust entry point to manage these services becomes paramount. Enter the API Gateway. More than just a simple proxy, an API Gateway is a powerful architectural pattern that centralizes common cross-cutting concerns, simplifying client-side applications and enhancing the overall system’s security and performance. In this comprehensive guide, we’ll dive deep into the core functionalities of an API Gateway: intelligent request routing, centralized authentication and authorization, and crucial rate limiting strategies. We’ll explore these concepts with practical code examples, architectural descriptions, and real-world scenarios, equipping you with the knowledge to implement them effectively in your own systems.

The Indispensable Role of an API Gateway in Modern Architectures

Imagine a distributed system composed of dozens, or even hundreds, of microservices. Without an API Gateway, clients would need to know the specific endpoint for each service, manage load balancing across multiple instances of a service, handle varying authentication mechanisms, and deal with potential service outages directly. This complexity quickly becomes unmanageable, leading to bloated client applications, increased development overhead, and significant security vulnerabilities.

An API Gateway acts as a single, unified entry point for all client requests. It sits between the client applications (web, mobile, IoT devices) and the backend microservices, abstracting away the complexity of the internal architecture. It’s the bouncer, the concierge, and the traffic cop all rolled into one, ensuring that requests are properly vetted, directed, and handled efficiently.

Why an API Gateway is Critical:

  • Simplifies Clients: Clients interact with a single, well-defined API, shielding them from the underlying microservice topology.
  • Centralized Cross-Cutting Concerns: It’s the ideal place to handle authentication, authorization, rate limiting, logging, monitoring, and caching, rather than duplicating this logic in every microservice.
  • Enhanced Security: By centralizing security policies, it provides a stronger defense against various threats and simplifies security audits.
  • Improved Performance: Can implement caching, compression, and request aggregation to optimize response times.
  • Greater Agility: Allows microservices to evolve independently without impacting client applications, as long as the gateway contract remains stable.
  • Polyglot Support: Can bridge different protocols and technologies used by various microservices.

Before we dive into the specific patterns, let’s visualize the basic setup of an API Gateway:


    +-----------------+        +---------------------+
    |     Clients     | <----->|     API Gateway     |
    | (Web, Mobile)   |        | (Single Entry Point)|
    +-----------------+        +---------------------+
                                       |
                                       | Requests are routed, authenticated,
                                       | rate-limited, etc.
                                       V
    +-----------------+   +-----------------+   +-----------------+
    |  Microservice A |<->|  Microservice B |<->|  Microservice C |
    | (e.g., Products)|   | (e.g., Orders)  |   | (e.g., Users)   |
    +-----------------+   +-----------------+   +-----------------+
    

This diagram illustrates the fundamental role of the API Gateway as the intermediary between clients and a multitude of backend services. Now, let’s explore the core patterns that make this intermediary so powerful.

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

Intelligent Request Routing: Directing Traffic with Precision

One of the primary functions of an API Gateway is to direct incoming client requests to the appropriate backend service. This isn’t just a simple pass-through; it involves sophisticated routing logic based on various criteria such as the request path, HTTP method, headers, query parameters, or even custom logic. Intelligent request routing ensures that requests reach the correct service instances, often balancing the load across them and abstracting the internal service URLs from clients.

How Request Routing Works

The API Gateway examines incoming requests and, based on predefined rules, determines which backend service should handle the request. This involves:

  • Path-Based Routing: The most common method, where the URL path dictates the target service. E.g., /products goes to the Product Service, /users to the User Service.
  • Host-Based Routing: Useful in multi-tenant or domain-specific scenarios, where different hostnames route to different services.
  • Header-Based Routing: Routing decisions based on custom HTTP headers, often used for A/B testing or canary deployments (e.g., X-Version: v2).
  • Method-Based Routing: Directing requests based on the HTTP method (GET, POST, PUT, DELETE) combined with the path.
  • Query Parameter-Based Routing: Routing based on the presence or value of query parameters.
  • Service Discovery Integration: Modern API Gateways often integrate with service discovery mechanisms (like Eureka, Consul, Kubernetes DNS) to dynamically locate available service instances, enabling resilience and scalability.
  • Load Balancing: After identifying the target service, the gateway often performs client-side load balancing to distribute requests across multiple instances of that service.

Architectural Description (Routing)


    [Client Request]
           |
           V
    +-----------------+
    |   API Gateway   |
    |-----------------|
    | 1. Parse Request|
    |    (URL, Method,|
    |     Headers)    |
    |                 |
    | 2. Routing Rules| <--- Maps (Path, Method, Headers) to Service ID
    |                 |
    | 3. Service Lookup| <--- (Optional) Service Discovery for Service ID -> IP:Port
    |                 |
    | 4. Load Balance | <--- (Optional) Distribute to available instances
    +-----------------+
           |
           V
    [Backend Microservice Instance]
    

Real-World Scenario: E-commerce API Routing

Consider an e-commerce platform with separate microservices for products, users, orders, and payments. The API Gateway would handle requests like this:

  • GET /api/products -> Product Service (list all products)
  • GET /api/products/{id} -> Product Service (get specific product)
  • POST /api/users -> User Service (create new user)
  • GET /api/orders/{id} -> Order Service (get specific order)
  • POST /api/payments -> Payment Service (process a payment)

Code Example: Spring Cloud Gateway Configuration

Spring Cloud Gateway is a popular choice for building API Gateways in the Spring ecosystem. Here's how you might configure routing using its YAML-based configuration:


    # application.yml for Spring Cloud Gateway
    spring:
      cloud:
        gateway:
          routes:
            - id: product_service_route
              uri: lb://PRODUCT-SERVICE # lb:// for load-balanced service discovery
              predicates:
                - Path=/api/products/**
              filters:
                - RewritePath=/api/(?<segment>.*), /$\{segment} # Remove /api prefix for downstream service
            - id: user_service_route
              uri: lb://USER-SERVICE
              predicates:
                - Path=/api/users/**
              filters:
                - RewritePath=/api/(?<segment>.*), /$\{segment}
            - id: order_service_route
              uri: http://localhost:8083 # Direct URL for a specific order service instance
              predicates:
                - Path=/api/orders/**
              filters:
                - RewritePath=/api/(?<segment>.*), /$\{segment}
    

In this example:

  • id: A unique identifier for the route.
  • uri: The target URI. lb://PRODUCT-SERVICE indicates that the gateway should use a load balancer (integrated with service discovery like Eureka) to find instances of the service named "PRODUCT-SERVICE". You can also use direct URLs like http://localhost:8083.
  • predicates: Define the conditions that must be met for a request to be routed through this route. Here, Path=/api/products/** means any request path starting with /api/products/.
  • filters: Allow modifying the request or response. RewritePath is used here to strip the /api/ prefix before forwarding the request to the downstream service, assuming the microservices themselves don't expect this prefix.

This configuration effectively directs requests to the correct backend services, leveraging service discovery for resilience and scalability.

Centralized Authentication and Authorization: The Security Gatekeeper

Security is paramount in any application, and in a microservices architecture, managing authentication and authorization across numerous services can be a significant challenge. An API Gateway is the ideal location to centralize these concerns, acting as a single security enforcement point for all incoming requests.

Authentication vs. Authorization

  • Authentication: Verifying the identity of a user or client. "Who are you?" (e.g., username/password, token validation).
  • Authorization: Determining what an authenticated user or client is permitted to do. "What are you allowed to do?" (e.g., roles, permissions).

How API Gateway Handles Security

By offloading authentication and initial authorization to the API Gateway, individual microservices can focus purely on their business logic, making them simpler, more secure, and easier to develop. The gateway performs the following:

  • Token Validation: Validates incoming JWTs (JSON Web Tokens), OAuth2 tokens, or API keys.
  • User Context Injection: After successful authentication, it can extract user information (user ID, roles, permissions) from the token and inject it into request headers or a custom context object, forwarding it to the downstream microservice. This allows the microservice to perform fine-grained authorization if needed.
  • Role-Based Access Control (RBAC): The gateway can enforce coarse-grained authorization rules based on user roles (e.g., only 'admin' users can access /admin endpoints).
  • API Key Management: For machine-to-machine communication or public APIs, it can validate API keys and enforce policies associated with them.
  • CORS Handling: Manages Cross-Origin Resource Sharing (CORS) policies centrally.

Architectural Description (Authentication & Authorization)


    [Client Request with Token]
             |
             V
    +-------------------+
    |    API Gateway    |
    |-------------------|
    | 1. Request Intercept|
    |                   |
    | 2. Auth Module    |
    |    - Validate Token (JWT, OAuth2) against Auth Server/Keys
    |    - If invalid: Reject (401 Unauthorized)
    |    - If valid: Extract User ID, Roles, Permissions
    |                   |
    | 3. Authz Module   |
    |    - Check if User/Role has access to requested resource/path
    |    - If unauthorized: Reject (403 Forbidden)
    |                   |
    | 4. Inject Context | <--- Add User ID, Roles to headers for downstream
    |                   |
    | 5. Forward Request|
    +-------------------+
             |
             V
    [Backend Microservice]
    (Receives trusted User Context in headers)
    

Real-World Scenario: Securing an E-commerce API

For our e-commerce platform, only authenticated users should be able to view their own orders or update their profile. Only administrators should be able to manage products. The API Gateway ensures this:

  • A user tries to access GET /api/orders/{id}. The gateway validates their JWT. If valid, it extracts the user ID and forwards it. The Order Service can then verify if {id} belongs to the authenticated user.
  • An unauthenticated user tries to access POST /api/products. The gateway immediately rejects the request with a 401 Unauthorized.
  • A regular user tries to access POST /api/products (assuming they have a valid token but no admin role). The gateway checks their roles from the token. If they lack the 'admin' role, it rejects the request with a 403 Forbidden.

Code Example: Kong API Gateway with JWT Plugin

Kong is a popular open-source API Gateway that uses a plugin-based architecture. Here's a simplified example of how you might configure JWT authentication for a service:


    # 1. Add a Service (e.g., our product service)
    curl -X POST http://localhost:8001/services \
        --data "name=product-service" \
        --data "url=http://product-service:8080"

    # 2. Add a Route to the Service
    curl -X POST http://localhost:8001/services/product-service/routes \
        --data "paths[]=/api/products"

    # 3. Enable the JWT plugin on the Service
    # This requires consumers to present a valid JWT
    curl -X POST http://localhost:8001/services/product-service/plugins \
        --data "name=jwt"

    # 4. (Optional) Create a Consumer and Associate a JWT Credential
    # In a real scenario, this would be done by your Auth Server/IdP
    curl -X POST http://localhost:8001/consumers \
        --data "username=testuser"

    curl -X POST http://localhost:8001/consumers/testuser/jwt \
        --data "key=your-jwt-key-id" \
        --data "secret=your-jwt-signing-secret" \
    

With this setup, any request to /api/products will be intercepted by Kong. The JWT plugin will attempt to validate the JWT provided in the Authorization header (e.g., Bearer <token>). If the token is valid, Kong will forward the request; otherwise, it will return a 401 Unauthorized response. Kong can also inject consumer information into headers for downstream services, like X-Consumer-ID or X-Consumer-Username, allowing microservices to identify the caller without re-validating the token.

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

Intelligent Rate Limiting: Protecting Your Resources

Rate limiting is a critical mechanism to control the rate at which clients can send requests to your API. Without it, a single malicious client or even a poorly written application could overwhelm your backend services, leading to degraded performance, service unavailability (DoS), or excessive resource consumption. Intelligent rate limiting protects your infrastructure, ensures fair usage, and helps maintain service stability.

Why Rate Limiting is Essential:

  • DDoS/DoS Prevention: Protects against denial-of-service attacks by blocking excessive requests from a single source.
  • Resource Protection: Prevents any single client from monopolizing server resources (CPU, memory, database connections).
  • Cost Control: Helps manage costs associated with resource usage, especially in cloud environments.
  • Fair Usage: Ensures that all legitimate users have equitable access to the API.
  • Monetization: Can be used to differentiate service tiers (e.g., free tier with lower limits, paid tier with higher limits).

Common Rate Limiting Algorithms

Different algorithms offer varying trade-offs in terms of complexity, fairness, and resource usage:

  • Fixed Window Counter:
    • Concept: A fixed time window (e.g., 60 seconds) is defined. Requests within that window are counted. Once the count exceeds the limit, further requests are rejected until the window resets.
    • Pros: Simple to implement.
    • Cons: Can suffer from "bursts" at the window boundaries (e.g., 100 requests at 59s and 100 requests at 61s, effectively 200 in 2 seconds).
  • Sliding Window Log:
    • Concept: Stores a timestamp for each request. When a new request arrives, it counts how many timestamps fall within the current window (e.g., last 60 seconds). If the count exceeds the limit, the request is rejected.
    • Pros: Highly accurate, avoids the "burst" problem of fixed window.
    • Cons: Can be memory intensive as it stores timestamps for every request.
  • Sliding Window Counter (or Weighted Counter):
    • Concept: Combines the simplicity of fixed window with the smoothness of sliding log. It uses two fixed windows: the current and the previous. The current window's count is weighted by the percentage of the window that has passed, and added to the previous window's full count.
    • Pros: Good balance of accuracy and efficiency.
    • Cons: Slightly more complex than fixed window.
  • Token Bucket:
    • Concept: A bucket holds "tokens." Tokens are added to the bucket at a fixed rate. Each request consumes one token. If the bucket is empty, the request is rejected or queued. The bucket has a maximum capacity.
    • Pros: Allows for bursts up to the bucket capacity, then smoothly throttles requests.
    • Cons: More complex to implement than fixed window.
  • Leaky Bucket:
    • Concept: Requests enter a queue (the bucket) at an arbitrary rate but "leak out" (are processed) at a constant, fixed rate. If the bucket is full, new requests are rejected.
    • Pros: Smooths out bursty traffic, ensures a consistent processing rate.
    • Cons: Can introduce latency due to queuing.

Architectural Description (Rate Limiting)


    [Client Request]
           |
           V
    +-----------------+
    |   API Gateway   |
    |-----------------|
    | 1. Identify Client| <--- By IP, User ID (from Auth), API Key
    |                 |
    | 2. Rate Limiting|
    |    - Check Policy (e.g., 100 req/min/client)
    |    - Access Counter/Bucket Storage (e.g., Redis)
    |    - If limit exceeded: Reject (429 Too Many Requests)
    |    - If within limit: Increment counter/Consume token
    |                 |
    | 3. Forward Request|
    +-----------------+
           |
           V
    [Backend Microservice]
    

For distributed rate limiting (essential in horizontally scaled gateways), a shared, high-performance data store like Redis is typically used to store and synchronize request counts or token bucket states across all gateway instances.

Real-World Scenario: Protecting a Public Data API

A public API that provides stock quotes might offer a free tier with a limit of 100 requests per minute per IP address, and a paid premium tier with a limit of 1000 requests per minute per authenticated user. The API Gateway enforces these differentiated limits:

  • An unauthenticated client (identified by IP) makes 101 requests in 60 seconds. The 101st request is rejected with a 429 status code.
  • A premium client (authenticated via JWT) makes 500 requests in 60 seconds. This is allowed. They make 1001 requests. The 1001st request is rejected.
  • The gateway ensures that the backend stock quote service is never overwhelmed by a single client, regardless of their tier, maintaining stability for all users.

Code Example: NGINX Rate Limiting

NGINX is a popular reverse proxy and can function as a powerful API Gateway. Its rate limiting capabilities are robust and widely used.


    # NGINX Configuration (nginx.conf)

    http {
        # Define a zone for rate limiting
        # `limit_req_zone $binary_remote_addr zone=my_ratelimit_zone:10m rate=10r/s;`
        # `zone=my_ratelimit_zone:10m`: Creates a shared memory zone named 'my_ratelimit_zone' of 10MB.
        # This zone stores the state for rate limiting (e.g., request counts for each IP).
        # `rate=10r/s`: Allows 10 requests per second.
        # `$binary_remote_addr`: Uses the client's IP address as the key for limiting.
        # This makes it memory-efficient as it stores a 4-byte hash for IPv4, 16-byte for IPv6.

        # For more complex scenarios, you might limit by authenticated user ID:
        # `limit_req_zone $http_x_user_id zone=user_ratelimit_zone:10m rate=50r/m;`
        # Requires the upstream service or another gateway component to set X-User-ID header.

        limit_req_zone $binary_remote_addr zone=api_clients:10m rate=10r/s;
        # Burst allows additional requests beyond the rate, but delays them.
        # nodelay means requests are rejected immediately if limit is reached.
        limit_req_zone $binary_remote_addr zone=api_burst:10m rate=5r/s burst=20 nodelay;


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

            location /api/public {
                # Apply the 'api_clients' rate limit zone.
                # `limit_req zone=api_clients;`
                # `limit_req_status 429;` sets the status code for rejected requests.
                # `limit_req_log_level info;` logs rejected requests.
                limit_req zone=api_clients burst=5 nodelay; # Allow 5 burst requests, then reject
                limit_req_status 429;
                proxy_pass http://public_service_backend;
            }

            location /api/premium {
                # Apply a stricter rate limit for premium endpoints
                # This assumes premium users might be identified by IP,
                # or you'd use a different key like $http_x_api_key or $http_authorization
                limit_req zone=api_burst; # Slower rate with a burst
                limit_req_status 429;
                proxy_pass http://premium_service_backend;
            }

            # If you need to limit by authenticated user, you would typically use a custom variable
            # that's set after authentication (e.g., from a JWT).
            # For instance, if a previous module extracts user ID to $user_id:
            # limit_req_zone $user_id zone=auth_users:10m rate=60r/m;
            #
            # location /api/authenticated {
            #     # Assume $user_id is set by an upstream auth proxy or a custom NGINX module
            #     limit_req zone=auth_users;
            #     limit_req_status 429;
            #     proxy_pass http://authenticated_service_backend;
            # }
        }
    }
    

In this NGINX configuration:

  • limit_req_zone defines a shared memory zone for storing rate limiting states. We define two zones, api_clients and api_burst, with different rates.
  • $binary_remote_addr is used as the key for limiting, meaning each unique client IP address will have its own counter.
  • rate=10r/s means 10 requests per second.
  • burst=5 allows an additional 5 requests beyond the configured rate to arrive in a burst. If nodelay is specified, these burst requests are processed immediately if resources are available, otherwise they are rejected. Without nodelay, they would be delayed.
  • limit_req applies the defined zone to a specific location (URI path).
  • limit_req_status 429; ensures that clients exceeding the limit receive an HTTP 429 Too Many Requests status code.

NGINX's powerful configuration allows for highly granular control over rate limiting, which can be tailored to various client types and API endpoints.

Beyond the Core: Other API Gateway Capabilities

While routing, authentication, and rate limiting are fundamental, API Gateways often provide a suite of other valuable features:

  • Request/Response Transformation: Modifying headers, body content, or query parameters to adapt between client expectations and backend service requirements.
  • Caching: Storing frequently accessed responses to reduce load on backend services and improve response times.
  • API Aggregation: Combining multiple backend service calls into a single response for clients, reducing client-side complexity and network overhead.
  • Circuit Breaking: Preventing cascading failures by quickly failing requests to services that are unresponsive, instead of waiting for timeouts.
  • Logging and Monitoring: Centralizing access logs, metrics, and distributed tracing information for better observability of the entire system.
  • Protocol Translation: Enabling clients to use different protocols (e.g., REST over HTTP/2) while backend services might use another (e.g., gRPC).
  • API Versioning: Managing different versions of your API, allowing older clients to continue using previous versions while new clients leverage updated APIs.

Popular API Gateway Solutions

The choice of an API Gateway depends on your specific needs, existing technology stack, and operational preferences. Here are some prominent options:

  • NGINX/NGINX Plus: A high-performance web server and reverse proxy, often configured to act as an API Gateway. Highly customizable with its configuration language and Lua scripting.
  • Kong: An open-source, cloud-native API Gateway built on top of NGINX and OpenResty. Known for its extensive plugin ecosystem for authentication, rate limiting, and more.
  • Spring Cloud Gateway: A reactive API Gateway built on Spring Framework 5, Project Reactor, and Spring Boot 2. Ideal for Spring-centric microservices architectures.
  • Envoy Proxy: A high-performance open-source edge and service proxy from Lyft. It's often used as a data plane in service mesh architectures (like Istio) but can also function as a standalone API Gateway.
  • Cloud Provider Gateways (AWS API Gateway, Azure API Management, Google Apigee): Managed services that offer comprehensive API Gateway functionalities, including integration with other cloud services, scalability, and security features out of the box. Excellent for organizations already heavily invested in a specific cloud ecosystem.
  • Tyk: An open-source API Gateway with a focus on performance, security, and developer portal features.

Each solution comes with its own strengths and weaknesses. NGINX is lightweight and performant; Kong has a rich plugin ecosystem; Spring Cloud Gateway fits seamlessly into a Java/Spring environment; and cloud-managed solutions offer operational convenience at a potentially higher cost and vendor lock-in risk.

Designing Your API Gateway Architecture

Implementing an API Gateway is more than just deploying a piece of software; it involves strategic architectural decisions:

  1. Choose the Right Gateway: Evaluate your team's expertise, existing tech stack, scalability requirements, and desired features against the capabilities of different gateway solutions. For example, if you're all-in on Spring Boot, Spring Cloud Gateway is a natural fit. If you need extreme performance and flexibility, NGINX or Envoy might be better.
  2. Deployment Strategy:
    • High Availability (HA): Deploy multiple instances of your API Gateway behind a load balancer to ensure no single point of failure.
    • Scalability: Design for horizontal scalability. Gateways should be stateless (or use external shared state like Redis for rate limiting) to allow easy scaling.
    • Containerization & Orchestration: Deploy gateways in containers (Docker) and manage them with orchestrators (Kubernetes) for efficient scaling and management.
  3. API Versioning: Decide how you'll manage API versions (e.g., URI versioning /v1/products, header versioning
Written by

Khader Vali

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

Share this article

Related Articles

Build Robust CLI Tools with Rust and Go for Developers

Aug 08, 2026 · 14 min read

Strangler Fig Pattern: Safely Migrating Monoliths to Microservices

Jul 19, 2026 · 16 min read

Strangler Fig Pattern: Safely Migrating Monoliths

Jun 19, 2026 · 19 min read