Empty mrt station with signs and advertisements.

API Gateway and Service Mesh Tools for Developers

CI/CD 2026-02-09 · 6 min read api-gateway service-mesh kong traefik envoy microservices
By DevTools Guide Editorial Team — Software engineers and developer advocates covering tools, workflows, and productivity for modern development teams.

API Gateway and Service Mesh Tools for Developers

Photo by Yazid N on Unsplash

When you have more than one service, you need something in front of them: routing requests, handling authentication, rate limiting, and providing observability. API gateways handle north-south traffic (clients to services). Service meshes handle east-west traffic (service to service). This guide covers the tools that matter, when you need each one, and how to set them up.

Traefik cloud-native API gateway logo

When You Need an API Gateway

You need an API gateway when:

You probably don't need one when you have a monolith or two to three services behind a simple reverse proxy.

Kong

Kong is the most widely deployed open-source API gateway. It's built on NGINX and OpenResty (Lua), with a plugin system that covers authentication, rate limiting, logging, and more.

Setup with Docker

# docker-compose.yml
services:
  kong-database:
    image: postgres:16
    environment:
      POSTGRES_USER: kong
      POSTGRES_DB: kong
      POSTGRES_PASSWORD: kongpass

  kong-migration:
    image: kong:3.6
    command: kong migrations bootstrap
    environment:
      KONG_DATABASE: postgres
      KONG_PG_HOST: kong-database
      KONG_PG_PASSWORD: kongpass
    depends_on:
      - kong-database

  kong:
    image: kong:3.6
    ports:
      - "8000:8000"   # proxy
      - "8001:8001"   # admin API
      - "8443:8443"   # proxy SSL
    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
    depends_on:
      - kong-migration

Configuring Routes

# Create a service
curl -i -X POST http://localhost:8001/services \
  --data name=users-service \
  --data url=http://users-api:3000

# Create a route for that service
curl -i -X POST http://localhost:8001/services/users-service/routes \
  --data paths[]=/api/users \
  --data strip_path=true

# Add rate limiting plugin
curl -i -X POST http://localhost:8001/services/users-service/plugins \
  --data name=rate-limiting \
  --data config.minute=100 \
  --data config.policy=local

# Add key authentication
curl -i -X POST http://localhost:8001/services/users-service/plugins \
  --data name=key-auth

Declarative Configuration

For production, use declarative configuration instead of the admin API:

# kong.yml
_format_version: "3.0"

services:
  - name: users-service
    url: http://users-api:3000
    routes:
      - name: users-route
        paths:
          - /api/users
        strip_path: true
    plugins:
      - name: rate-limiting
        config:
          minute: 100
          policy: local
      - name: jwt
        config:
          claims_to_verify:
            - exp

  - name: orders-service
    url: http://orders-api:3000
    routes:
      - name: orders-route
        paths:
          - /api/orders
        strip_path: true
# Apply declarative config
kong config db_import kong.yml

# Or run Kong in DB-less mode (no Postgres needed)
# Set KONG_DATABASE=off and KONG_DECLARATIVE_CONFIG=/path/to/kong.yml

Strengths: Huge plugin ecosystem (100+ plugins), battle-tested at scale, DB-less mode for simple deployments, good documentation, active community.

Weaknesses: Lua-based plugin development is niche, the Postgres dependency adds complexity for small deployments, Kong's commercial features (Kong Konnect) overlap with open-source features.

Traefik

Traefik is a modern reverse proxy and API gateway that integrates natively with Docker, Kubernetes, and other orchestrators. It automatically discovers services and configures routing -- no manual registration needed.

Docker Integration

# docker-compose.yml
services:
  traefik:
    image: traefik:v3.0
    command:
      - "--api.insecure=true"
      - "--providers.docker=true"
      - "--providers.docker.exposedbydefault=false"
      - "--entrypoints.web.address=:80"
      - "--entrypoints.websecure.address=:443"
      - "--certificatesresolvers.letsencrypt.acme.email=admin@example.com"
      - "--certificatesresolvers.letsencrypt.acme.storage=/letsencrypt/acme.json"
      - "--certificatesresolvers.letsencrypt.acme.httpchallenge.entrypoint=web"
    ports:
      - "80:80"
      - "443:443"
      - "8080:8080"  # dashboard
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
      - letsencrypt:/letsencrypt

  users-api:
    image: users-api:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.users.rule=Host(`api.example.com`) && PathPrefix(`/users`)"
      - "traefik.http.routers.users.entrypoints=websecure"
      - "traefik.http.routers.users.tls.certresolver=letsencrypt"
      - "traefik.http.services.users.loadbalancer.server.port=3000"

  orders-api:
    image: orders-api:latest
    labels:
      - "traefik.enable=true"
      - "traefik.http.routers.orders.rule=Host(`api.example.com`) && PathPrefix(`/orders`)"
      - "traefik.http.routers.orders.entrypoints=websecure"
      - "traefik.http.routers.orders.tls.certresolver=letsencrypt"
      - "traefik.http.services.orders.loadbalancer.server.port=3000"

volumes:
  letsencrypt:

Middleware

Traefik's middleware chain handles cross-cutting concerns:

# As Docker labels
labels:
  # Rate limiting
  - "traefik.http.middlewares.ratelimit.ratelimit.average=100"
  - "traefik.http.middlewares.ratelimit.ratelimit.burst=50"

  # Authentication (forward auth to an external service)
  - "traefik.http.middlewares.auth.forwardauth.address=http://auth-service:3000/verify"
  - "traefik.http.middlewares.auth.forwardauth.authResponseHeaders=X-User-Id,X-User-Role"

  # Apply middleware to a router
  - "traefik.http.routers.users.middlewares=ratelimit,auth"

Strengths: Automatic service discovery (Docker, Kubernetes, Consul), automatic Let's Encrypt certificates, excellent dashboard, configuration via labels (no separate config files), hot reload without restarts.

Weaknesses: Docker label configuration gets verbose for complex setups, less plugin variety than Kong, debugging routing issues can be frustrating.

Best for: Docker-based deployments where automatic service discovery and Let's Encrypt integration matter.

Want more ci/cd guides? Get guides like this in your inbox — DevTools Guide delivers one free deep-dive every week.

NGINX

NGINX is the workhorse of the internet. It's not specifically an API gateway, but it handles the job for many teams with straightforward configuration.

# /etc/nginx/conf.d/api-gateway.conf
upstream users_api {
    server users-api:3000;
}

upstream orders_api {
    server orders-api:3000;
}

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

    # Rate limiting
    limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;

    location /api/users/ {
        limit_req zone=api burst=20 nodelay;
        proxy_pass http://users_api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }

    location /api/orders/ {
        limit_req zone=api burst=20 nodelay;
        proxy_pass http://orders_api/;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }

    # Health check
    location /health {
        return 200 "OK";
    }
}

Strengths: Proven at massive scale, everyone knows it, excellent performance, simple configuration for simple use cases.

Weaknesses: No service discovery, no automatic certificate management (need certbot), no API-specific features (no request/response transformation, no built-in auth plugins), config changes require reload.

Best for: Simple routing and load balancing where you don't need API gateway features. Also works as the base layer under more specialized tools.

Envoy Proxy

Envoy is a high-performance proxy designed for service mesh architectures. It's the data plane for Istio, and it's increasingly used as a standalone API gateway.

# envoy.yaml
static_resources:
  listeners:
    - name: listener_0
      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
                route_config:
                  name: local_route
                  virtual_hosts:
                    - name: backend
                      domains: ["*"]
                      routes:
                        - match:
                            prefix: "/api/users"
                          route:
                            cluster: users_service
                        - match:
                            prefix: "/api/orders"
                          route:
                            cluster: orders_service
                http_filters:
                  - name: envoy.filters.http.router

  clusters:
    - name: users_service
      connect_timeout: 5s
      type: STRICT_DNS
      load_assignment:
        cluster_name: users_service
        endpoints:
          - lb_endpoints:
              - endpoint:
                  address:
                    socket_address:
                      address: users-api
                      port_value: 3000

Strengths: Exceptional performance, advanced load balancing (circuit breaking, outlier detection, retries), rich observability (metrics, distributed tracing, access logs), hot restartable, xDS API for dynamic configuration.

Weaknesses: Configuration is verbose and complex (YAML/protobuf), steep learning curve, overkill for simple deployments.

Best for: High-performance requirements, service mesh data plane, teams that need advanced traffic management.

Service Meshes (When You Need Them)

A service mesh handles communication between services: mTLS, load balancing, retries, circuit breaking, and observability -- all without changing application code.

Istio

Istio is the most feature-rich service mesh. It uses Envoy as its data plane.

Strengths: Comprehensive feature set, strong security (automatic mTLS), traffic management (canary deployments, fault injection), deep observability.

Weaknesses: Complex to operate, significant resource overhead (Envoy sidecar in every pod), steep learning curve, can be slow to start.

Linkerd

Linkerd is a simpler, lighter alternative to Istio. It has its own Rust-based proxy instead of Envoy.

Strengths: Simpler than Istio, lower resource overhead, easier to operate, excellent documentation, CNCF graduated project.

Weaknesses: Fewer features than Istio, smaller ecosystem.

When you need a service mesh: When you have 10+ services and need automatic mTLS, observability across services, and traffic management that's too complex for an API gateway alone. If you have fewer than 10 services, a service mesh is overhead you don't need.

Comparison

Feature Kong Traefik NGINX Envoy
Primary Use API Gateway Reverse Proxy/Gateway Reverse Proxy Service Proxy
Service Discovery Plugin Native (Docker/K8s) No xDS API
Auto TLS Plugin Built-in (Let's Encrypt) Certbot SDS
Rate Limiting Plugin Middleware Module Filter
Auth Plugins Extensive Forward Auth Basic Auth External
Dashboard Kong Manager Built-in Third-party Admin API
Configuration Admin API/YAML Labels/YAML Config files YAML/xDS
Best For API management Docker/K8s routing Simple proxying High-perf mesh

Recommendations

Get free weekly tips in your inbox. Subscribe to DevTools Guide

More ci/cd guides

One focused tutorial every week — no spam, unsubscribe anytime.

Opens Substack to confirm — no spam, unsubscribe anytime.

Before you go...

Get a free weekly guide from DevTools Guide — one focused topic, delivered every week. No spam.

Opens Substack to confirm — no spam, unsubscribe anytime.