API Gateway Concepts — Kong, NGINX, and AWS API Gateway Guide
In this tutorial, you'll learn about API Gateway Concepts. We cover key concepts, practical examples, and best practices to help you understand and apply this topic effectively.
An API Gateway is a server that acts as a single entry point for all client requests, handling routing, Rate Limiting, authentication, request transformation, and aggregation across multiple backend services in a microservice architecture.
What You'll Learn
You will learn what API gateways do, compare Kong, NGINX, and AWS API Gateway, implement routing and Rate Limiting with each, and design a gateway architecture for Microservices.
Why API Gateways Matter
Without an API Gateway, every client must know the location of every microservice, handle authentication individually, and implement its own Rate Limiting and logging. A gateway centralizes these cross-cutting concerns, reduces client complexity by up to 60 percent, and provides a single security enforcement point.
Real-World Use
DodaTech uses API gateways across its infrastructure. Doda Browser traffic routes through Kong, DodaZIP update distribution uses NGINX as a reverse Proxy, and Durga Antivirus Pro threat intelligence APIs are behind AWS API Gateway for Serverless integration.
API Gateway Learning Path
flowchart LR
A[Microservices Basics] --> B[Gateway Concepts]
B --> C[Kong Gateway]
B --> D[NGINX Gateway]
B --> E[AWS API Gateway]
C --> F[Routing & Plugins]
D --> F
E --> F
B:::current
classDef current fill:#f90,color:#fff,stroke:#333,stroke-width:2px
Prerequisites
Understand RESTful Api Design Best Practices and API Development Concepts. Familiarity with Cloud Computing Basics helps. Basic knowledge of Docker Basics is useful for running gateway software locally.
What is an API Gateway?
graph TD
Client1[Web App] --> Gateway[API Gateway]
Client2[Mobile App] --> Gateway
Client3[Third Party] --> Gateway
Gateway --> Service1[Users Service]
Gateway --> Service2[Orders Service]
Gateway --> Service3[Products Service]
Gateway --> Service4[Notifications Service]
Gateway --> Auth[Auth Service]
Gateway --> RateLimit[Rate Limiter]
Gateway --> Cache[Cache Layer]
Core Responsibilities
| Function | Description |
|---|---|
| Request Routing | Forward requests to the correct backend service |
| Authentication | Validate tokens and API keys |
| Rate Limiting | Enforce request quotas |
| Load Balancing | Distribute requests across service instances |
| Request/Response Transformation | Modify headers, bodies, protocols |
| Caching | Cache responses to reduce backend load |
| Logging & Monitoring | Centralize request logging |
| Circuit Breaking | Stop forwarding to failing services |
| API Versioning | Route different versions to different backends |
Kong Gateway
Kong is an open-source API Gateway built on NGINX with a plugin architecture.
Installing Kong with Docker
# docker-compose.yml
version: '3'
services:
kong-database:
image: postgres:15
environment:
POSTGRES_DB: kong
POSTGRES_USER: kong
POSTGRES_PASSWORD: kongpass
kong-migrations:
image: kong:3.7
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: kong-database
KONG_PG_PASSWORD: kongpass
command: "kong migrations bootstrap"
depends_on:
- kong-database
kong:
image: kong:3.7
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: kong-database
KONG_PG_PASSWORD: kongpass
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
KONG_ADMIN_LISTEN: "0.0.0.0:8001"
ports:
- "8000:8000" # Proxy port
- "8443:8443" # Proxy HTTPS
- "8001:8001" # Admin API
depends_on:
- kong-migrations
Configuring Kong
# Add a service
curl -s -X POST http://localhost:8001/services \
--data name=user-service \
--data url=http://user-service:3000
# Add a route to the service
curl -s -X POST http://localhost:8001/services/user-service/routes \
--data paths[]=/api/v1/users \
--data name=users-route
# Enable rate limiting plugin
curl -s -X POST http://localhost:8001/services/user-service/plugins \
--data name=rate-limiting \
--data config.minute=100 \
--data config.policy=local
# Enable JWT authentication
curl -s -X POST http://localhost:8001/services/user-service/plugins \
--data name=jwt
# Enable CORS
curl -s -X POST http://localhost:8001/services/user-service/plugins \
--data name=cors \
--data config.origins=https://dodatech.com \
--data config.methods=GET,POST,PUT,DELETE
Kong Plugins
| Plugin | Purpose |
|---|---|
| rate-limiting | Request Rate Limiting |
| JWT | JWT token validation |
| key-auth | API key authentication |
| CORS | CORS header management |
| ip-restriction | IP whitelist/blacklist |
| acl | Access control lists |
| request-transformer | Header/body modification |
| response-transformer | Response header/body modification |
| prometheus | Metrics export |
| file-log | Request logging to file |
NGINX as API Gateway
NGINX can function as a lightweight API Gateway without additional dependencies.
# /etc/nginx/nginx.conf
events {
worker_connections 1024;
}
http {
upstream user_service {
server user-service-1:3000 weight=3;
server user-service-2:3000 weight=2;
server user-service-3:3000 backup;
}
upstream order_service {
server order-service:4000;
}
# Rate limit zones
limit_req_zone $binary_remote_addr zone=api_limit:10m rate=100r/s;
limit_req_zone $binary_remote_addr zone=auth_limit:10m rate=5r/s;
server {
listen 443 ssl;
server_name api.dodatech.com;
ssl_certificate /etc/ssl/certs/dodatech.crt;
ssl_certificate_key /etc/ssl/private/dodatech.key;
# Security headers
add_header Strict-Transport-Security "max-age=31536000" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "DENY" always;
# CORS preflight
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Origin "https://dodatech.com";
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, PATCH";
add_header Access-Control-Allow-Headers "Content-Type, Authorization";
add_header Access-Control-Max-Age 86400;
return 204;
}
# User service routes
location /api/v1/users {
limit_req zone=api_limit burst=20 nodelay;
# JWT validation via auth request
auth_request /_auth;
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;
}
# Order service routes
location /api/v1/orders {
limit_req zone=api_limit burst=20 nodelay;
auth_request /_auth;
proxy_pass http://order_service;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
}
# Auth service (internal only)
location /_auth {
internal;
proxy_pass http://auth-service:5000/validate;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
proxy_set_header X-Original-URI $request_uri;
}
# Stricter rate limit on auth endpoints
location /api/v1/auth/login {
limit_req zone=auth_limit burst=5 nodelay;
proxy_pass http://auth-service:5000;
}
# Error handling
error_page 429 /429.json;
location = /429.json {
return 429 '{"error":"rate_limited","message":"Too many requests"}';
}
error_page 401 /401.json;
location = /401.json {
return 401 '{"error":"unauthorized","message":"Authentication required"}';
}
}
}
NGINX Metrics with Status Module
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
Expected output:
Active connections: 42
server accepts handled requests
12345 12345 67890
Reading: 3 Writing: 15 Waiting: 24
AWS API Gateway
AWS API Gateway is a fully managed service for creating, deploying, and managing APIs at scale.
Serverless REST API Configuration
# Serverless.yml (with Serverless Framework)
service: dodatech-API-gateway
provider:
name: AWS
runtime: nodejs20.x
region: us-east-1
functions:
listUsers:
handler: handlers/users.list
events:
- HTTP:
path: /v1/users
method: GET
CORS: true
authorizer: AWS_iam
throttling:
burstLimit: 100
rateLimit: 50
createUser:
handler: handlers/users.create
events:
- HTTP:
path: /v1/users
method: POST
CORS: true
authorizer:
type: COGNITO_USER_POOLS
authorizerId: !Ref ApiGatewayAuthorizer
AWS API Gateway Features
| Feature | Configuration |
|---|---|
| Throttling | Burst limit and rate limit per endpoint |
| Caching | Configurable TTL per stage |
| Authentication | Cognito, IAM, Lambda authorizer, API keys |
| Request Validation | Validate body, headers, query parameters |
| Request Transformation | Mapping templates with VTL |
| Stage Variables | Environment-specific configuration |
| Custom Domains | Custom domain with ACM certificate |
| Usage Plans | API key-based usage quotas |
Terraform Configuration
resource "AWS_API_gateway_REST_API" "dodatech_API" {
name = "DodaTech API"
description = "DodaTech API Gateway"
}
resource "AWS_API_gateway_resource" "users" {
REST_API_id = AWS_API_gateway_REST_API.dodatech_API.id
parent_id = AWS_API_gateway_REST_API.dodatech_API.root_resource_id
path_part = "users"
}
resource "AWS_API_gateway_method" "users_get" {
REST_API_id = AWS_API_gateway_REST_API.dodatech_API.id
resource_id = AWS_API_gateway_resource.users.id
HTTP_method = "GET"
authorization = "COGNITO_USER_POOLS"
authorizer_id = AWS_API_gateway_authorizer.cognito.id
}
resource "AWS_API_gateway_deployment" "prod" {
REST_API_id = AWS_API_gateway_REST_API.dodatech_API.id
stage_name = "prod"
}
Choosing an API Gateway
| Factor | Kong | NGINX | AWS API Gateway |
|---|---|---|---|
| Setup effort | Medium | Medium | Low (managed) |
| Performance | High | Very High | High |
| Plugin ecosystem | 200+ plugins | Limited (modules) | AWS service integration |
| Cost | Free (self-hosted) | Free | Pay per request |
| Scaling | Manual | Manual | Auto-scaling |
| Learning curve | Medium | Medium | Low |
| Customization | High | Very High | Medium |
Common Errors
No Rate Limiting at gateway level — Relying only on application-level Rate Limiting. Attackers can bypass individual services. Enforce rate limits at the gateway level as the first line of defense.
Exposing internal service URLs — Clients can see or guess internal service URLs. The gateway should abstract all internal routing. Never expose internal hostnames or ports.
Single point of failure — Running a single gateway instance. Deploy multiple gateway instances behind a load balancer. Use health checks to detect failures.
Too much logic in the gateway — Implementing business logic in the gateway instead of backend services. The gateway should handle cross-cutting concerns only. Business logic belongs in services.
No circuit breaking — Continuing to forward requests to failing services. Implement circuit breakers that stop routing to unhealthy instances after a threshold of failures.
Ignoring WebSocket support — Choosing a gateway that does not support WebSocket for applications that need real-time features. Kong and NGINX support WebSocket proxying.
No request ID tracing — Not propagating request IDs across services. Configure the gateway to generate and propagate unique request IDs in headers for distributed tracing.
Practice Questions
- What are the primary functions of an API Gateway?
- How does Kong differ from NGINX as an API Gateway?
- What is the purpose of Rate Limiting at the gateway level?
- How does AWS API Gateway handle authentication?
- What is circuit breaking and why is it important?
Challenge
Design and deploy an API Gateway architecture for a microservice system with six services. Configure Kong with: routing rules for each service, JWT authentication with a plugin, Rate Limiting (100/min standard, 5/min for auth), CORS for two domains, request logging to stdout, and circuit breaking with a 5-second timeout. Write Docker Compose configuration for all services and the gateway.
FAQ
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro