API Gateway Pattern in Production: Kong, AWS, Azure, Spring and NestJS

How I have used API gateway patterns across financial services, retail master-data, procurement/e-auction and travel platforms, including routing, authentication, throttling, resilience and gateway failure design.

Romharshan Singh
Romharshan SinghSenior Solution Architect • AI & Cloud Mentor
1 September 20265 min read0 viewsUpdated 1 Sept 2026
API Gateway Pattern in Production: Kong, AWS, Azure, Spring and NestJS

API Gateway Pattern in Production: Kong, AWS, Azure, Spring and NestJS

Why I use a gateway

I have used several API gateway approaches across different projects. I do not believe there is one gateway product that is automatically correct for every system.

In financial-services work, I used Kong where centralized traffic policy, authentication, throttling and auditability were important. In a Lululemon product/location data-management program, I worked with AWS API Gateway as part of the integration boundary. In an RFx/e-auction environment associated with Reliance/Tech Mahindra, I used Azure API Management-style gateway capabilities around procurement workflows. In travel-booking work at Thomas Cook, I used Spring-based gateway/service layers in front of flight, hotel and other booking capabilities. I have also built lighter gateway/BFF layers in Node.js, Express and NestJS.

The architecture details in this article are intentionally generalized. I am describing patterns and decisions from my own work, not publishing confidential client internals.

A gateway gives clients one controlled entry point:

plaintext
Mobile / Web / Partner
          |
          v
      API Gateway
   /      |       \
Auth   Rate Limit  Routing
          |
          v
  -----------------------
  | Booking | Payment   |
  | Vendor  | Auction   |
  | Product | Customer  |
  -----------------------

The gateway is valuable because every backend service should not independently reinvent token validation, quota logic, correlation IDs, TLS policy and public route structure.

But there is an equally important rule: I do not put core business logic into the gateway. When the gateway becomes the place where workflows, database lookups and domain decisions accumulate, it becomes another monolith.

Kong in financial-services style workloads

For a financial-service boundary I normally care about more than routing:

  • consumer/client identity;
  • OAuth/JWT scopes;
  • per-client quotas;
  • burst control;
  • IP/network restrictions;
  • correlation identifiers;
  • audit metadata;
  • safe request-size limits.

A small Kong declarative example:

yaml
_format_version: "3.0"

services:
  - name: payment-service
    url: http://payment-service:8080
    routes:
      - name: payment-api
        paths:
          - /api/payments

plugins:
  - name: correlation-id
    service: payment-service
    config:
      header_name: X-Request-ID
      generator: uuid

  - name: rate-limiting
    service: payment-service
    config:
      minute: 120
      policy: local

For sensitive operations I still enforce authorization inside the business service. The gateway can establish identity; the service must decide whether that identity can perform a particular business action.

AWS API Gateway in enterprise integration

In product/location master-data integration, the gateway can front stable enterprise APIs while backend services and event flows evolve independently.

plaintext
Enterprise / Partner Systems
             |
             v
       AWS API Gateway
             |
        VPC / private link
             |
      Domain Services
             |
           Kafka
             |
      Downstream consumers

A simplified OpenAPI integration:

yaml
paths:
  /products/{id}:
    get:
      responses:
        "200":
          description: Product
      x-amazon-apigateway-integration:
        type: http_proxy
        httpMethod: GET
        uri: "http://product-service.internal/products/{id}"
        connectionType: VPC_LINK
        connectionId: "${stageVariables.vpcLinkId}"
        timeoutInMillis: 2900

I keep the gateway timeout aligned with the complete request budget. If the client SLA is three seconds, allowing a downstream integration to wait for twenty seconds is already an architecture defect.

Azure API Management for RFx / e-auction

Auction and procurement systems have unusual traffic characteristics: bid windows, bursts near close time, supplier identity, duplicate submissions and audit requirements.

A conceptual route is:

plaintext
Supplier / Buyer
       |
       v
Azure API Management
       |
  --------------
  | RFx API    |
  | Bid API    |
  | Vendor API |
  | Audit API  |
  --------------

The gateway can throttle or authenticate, but duplicate bid protection belongs in the application through an idempotency/business-operation key.

A lightweight NestJS gateway

Sometimes a managed or self-hosted gateway product is unnecessary. A small NestJS edge/BFF can be enough.

typescript
@Injectable()
export class GatewayProxyService {
  constructor(private readonly http: HttpService) {}

  async forward<T>(
    targetUrl: string,
    requestId: string,
    payload: unknown,
  ): Promise<T> {
    const result = await firstValueFrom(
      this.http.post<T>(targetUrl, payload, {
        timeout: 2500,
        headers: { 'x-request-id': requestId },
      }).pipe(
        retry({
          count: 2,
          delay: (error, retryCount) => {
            if (!isTransient(error)) {
              throw error;
            }

            const base = 100 * 2 ** (retryCount - 1);
            const jitter = Math.floor(Math.random() * 80);
            return timer(base + jitter);
          },
        }),
      ),
    );

    return result.data;
  }
}

I would not copy this retry policy blindly. The operation must be safe to retry and the entire attempt sequence must remain inside the caller's deadline.

The failure case I care about most: retry multiplication

Imagine:

plaintext
Client retries 2 times
Gateway retries 2 times
Service SDK retries 3 times

One user request can create many downstream attempts. During an outage that is exactly when the failing system least needs extra traffic.

I therefore assign one retry owner for each dependency call.

Gateway observability

At minimum I want:

plaintext
request_id
consumer/client
route
HTTP status
upstream status
gateway latency
upstream latency
rate-limit rejection
timeout count
request size
response size

Gateway latency and upstream latency must be separate. Otherwise an operator cannot tell whether the gateway itself is slow or the backend is slow.

When I would not use a heavyweight API gateway

For one small internal service, Kubernetes Ingress or a simple reverse proxy may be enough.

For a frontend-specific aggregation layer, a BFF may be better.

For internal service-to-service traffic, I normally do not route every request back through the public edge gateway.

Production checklist

  • Keep the gateway stateless where possible.
  • Run multiple replicas or use a managed HA gateway.
  • Bound connect and request timeouts.
  • Define exactly where retries happen.
  • Propagate trace and correlation IDs.
  • Apply rate limits by the correct consumer identity.
  • Keep domain authorization in owning services.
  • Load-test burst behavior.
  • Monitor upstream latency separately.
  • Test the gateway itself as a failure domain.

FAQ

Is Kong better than AWS API Gateway?

Not universally. Kong gives strong self-hosted/plugin flexibility. AWS API Gateway removes gateway-cluster operations and integrates deeply with AWS. I choose based on platform, policy, traffic and operating model.

Should internal services call each other through the edge gateway?

Usually no. Platform-native service discovery or internal routing is normally better.

Should authentication live only in the gateway?

The gateway can validate identity/token shape. Business authorization still belongs close to the protected business capability.

Can Spring Cloud Gateway replace Kong?

For many application-owned gateway scenarios, yes. But Kong and managed gateways provide operational and policy ecosystems that may be useful when many teams/APIs share the boundary.

- [Microservices Design Patterns I Have Used in Real Enterprise Projects](/articles/microservices-design-patterns-real-enterprise-projects) - [Service Discovery in Microservices](/articles/service-discovery-kubernetes-dns-consul-cloud)
Was this article useful?

Your feedback helps prioritize deeper technical content.

Romharshan Singh
ABOUT THE AUTHOR

Romharshan Singh

Senior Solution Architect and Full Stack Technology Leader with 20+ years of enterprise engineering experience across AI, cloud, distributed systems, Java, Node.js, React, Angular, Kafka and Kubernetes.