Istio service mesh and an API gateway are not direct substitutes. Istio secures service-to-service traffic, while an API gateway publishes and governs external APIs.
The real risk is assigning one layer another's job. That mistake creates duplicate controls, unclear ownership, and avoidable AWS costs.
Choose istio, gateway API, or API management
Use each layer for its own job. Gateway API declares Kubernetes entry traffic, Istio enforces workload identity and policy, and API management handles consumer accounts.
A service mesh controls service-to-service calls. Think of it as badge readers inside an office building. Workloads prove identity before they can speak to each other.
Istio often enforces mutual TLS, or mTLS. With mTLS, both sides prove identity before sharing data.
An API gateway is the public reception desk. It checks client credentials and forwards valid requests from mobile apps, partners, and customers.
Gateway API defines the front door. It declares listeners, hostnames, and routes in Kubernetes.
Use Istio for internal workload trust, Gateway API for Kubernetes routing, and API management for external consumer programs.
For most AWS Kubernetes teams, run Gateway API with Istio at the edge. Add API management only when consumers need accounts, plans, or a portal. Do not add a second gateway just because it has familiar API features. A simple public API may need only one load balancer and Gateway API. Sensitive internal services still need mTLS and authorization rules.
Decision matrix for AWS Kubernetes
| Requirement | Best primary choice | What it does not replace | Typical monthly AWS cost |
|---|
| Internal workload identity and mTLS | Istio service mesh | Consumer portal or billing | Cluster compute, often $150 to $600 for dedicated capacity |
| HTTP exposure and path routing | Gateway API with Istio | API product lifecycle | Usually one load balancer, about $20 to $60 before data charges |
| Partner plans, API keys, monetization | Dedicated API management | East-west mTLS | Often $100 to $1,000+ based on traffic and vendor |
| One basic internal HTTP app | Classic Ingress or Gateway API | Zero Trust segmentation | Usually $20 to $60 for the load balancer |
These planning ranges exclude data transfer, WAF requests, Availability Zones, and managed control-plane costs.
Why edge routing is not API management
Istio can route and secure an API. JWT validation alone does not create partner sign-up, a developer catalog, or usage billing.
Capabilities istio can enforce
Istio's Envoy Proxy data plane can apply routing, timeouts, retries, traffic splits, JWT validation, and authorization policy. It can send request signals to OpenTelemetry tools.
Those signals help trace a request across microservices. Istio's strongest use is service-to-service authentication.
A payment service can accept calls only from a named checkout workload. This works even when both services run in one cluster.
The most common mistake here is treating a valid JWT as full authorization. A token can prove a user identity, but it does not prove workload trust.
Capabilities that need API management
A dedicated API management layer owns the consumer relationship. It can offer a developer portal, documentation, self-service keys, subscriptions, and API products.
It can also track use by consumer and apply plan limits. Those features matter when partners or customers consume your API.
This split supports Zero Trust. The mesh controls workload traffic, while the public edge handles consumer identity and external API controls.
Traffic ownership at a glance:
Internet client
OAuth 2.0 / WAFGateway API
listener + routeIstio ingress
policy enforcementMesh workload
mTLS + authorization
API management belongs before or alongside the public entry point. Mesh authorization continues after the request reaches Kubernetes.
Edge routing decides where a request goes. The next section shows how to decide whether that request should proceed.
Secure external traffic beyond TLS
TLS encrypts traffic. Zero Trust also checks sender identity, allowed actions, and trust at each internal hop.
Apply controls in the right order
Place a Web Application Firewall before the public endpoint. It blocks common attacks and high-volume abuse.
Use API management when limits depend on a customer plan or API key. Use Istio authorization when access depends on claims, source workload, HTTP method, or path.
A valid token at the load balancer does not authorize a reporting service to call a database API.
This is where many designs fail. They protect the front door but leave internal doors open.
TLS, redirects, and certificates
Use cert-manager to request and renew certificates. Do not copy certificate files into Kubernetes Secrets by hand.
Redirect port 80 to port 443. Attach the certificate Secret to the HTTPS listener.
Monitor edge failures and upstream failures. HTTP 401 or 403 usually means authentication or authorization blocked the request.
HTTP 503 often means the route matched, but the Service may have no healthy endpoints.
A production edge needs policy objects besides an HTTPS listener. Create a cert-manager Certificate in the Gateway namespace.
That resource writes the api-tls Secret used by the listener. Use an approved ClusterIssuer or Issuer for api.example.com.
RequestAuthentication can validate JWT issuer, audience, and JWKS signatures. AuthorizationPolicy decides which principals and claims can call a path.
OAuth 2.0 login, consent, and token issuance belong elsewhere. An identity provider or API management layer should handle those tasks.
Istio validates the resulting token. It should not become your customer identity system.
Keep workload authorization separate from consumer authorization. Rate limiting also needs an explicit design.
Local Envoy limits protect one gateway instance. Tenant-wide quotas usually need an external rate-limit service or API management.
These edge controls matter first. Internal traffic needs its own identity model after the request enters the cluster.
Protect east-west traffic inside the mesh
East-west traffic should use mTLS, service accounts, and Istio AuthorizationPolicy. Repeated ingress rules cannot replace these controls.
Enforce workload identity with mTLS
mTLS gives both workloads a cryptographic identity. Istio can issue and rotate certificates between Envoy proxies.
AuthorizationPolicy then limits allowed callers. For example, allow checkout in store to call /charge.
The same rule can deny catalog. This creates identity-based segments instead of trust based on Kubernetes IP addresses.
A common case is a compromised catalog Pod. mTLS and policy can stop it from calling the payment endpoint.
Control outbound calls with egress policy
A ServiceEntry registers an external destination as a known dependency. An egress gateway gives workloads a controlled exit point.
Use it for payment processors, SaaS tools, and legacy endpoints. Log source identity, destination hostname, and policy result.
Those logs help incident response teams see more than shared NAT traffic. They show which workload attempted each external call.
mTLS limits internal trust. The next task is making routes work and finding failures without changing every policy.
Build routes, diagnose failures, migrate safely
Gateway API separates infrastructure ownership from application routing. Routes must match names, namespaces, ports, selectors, hostnames, and Service endpoints.
Deploy a minimal secure route
The following manifest creates a namespace, workload, Service, GatewayClass, HTTPS Gateway, redirect route, and application route.
YAML
apiVersion: v1
kind: Namespace
metadata: {name: store}
apiVersion: apps/v1
kind: Deployment
metadata: {name: catalog, namespace: store}
spec:
replicas: 2
selector: {matchLabels: {app: catalog}}
template:
metadata: {labels: {app: catalog}}
spec:
serviceAccountName: catalog
containers:
- name: app
image: hashicorp/http-echo:1.0
args: ["-text=catalog ok"]
ports: [{containerPort: 5678}]
apiVersion: v1
kind: Service
metadata: {name: catalog, namespace: store}
spec:
selector: {app: catalog}
ports: [{name: http, port: 8080, targetPort: 5678}]
apiVersion: gateway.networking.k8s.io/v1
kind: GatewayClass
metadata: {name: istio-public}
spec: {controllerName: istio.io/gateway-controller}
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata: {name: public, namespace: store}
spec:
gatewayClassName: istio-public
listeners:
- {name: http, protocol: HTTP, port: 80, hostname: api.example.com}
- name: https
protocol: HTTPS
port: 443
hostname: api.example.com
tls: {mode: Terminate, certificateRefs: [{name: api-tls}]}
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata: {name: redirect-http, namespace: store}
spec:
parentRefs: [{name: public, sectionName: http}]
hostnames: [api.example.com]
rules: [{filters: [{type: RequestRedirect, requestRedirect: {scheme: https, statusCode: 301}}]}]
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata: {name: catalog-route, namespace: store}
spec:
parentRefs: [{name: public, sectionName: https}]
hostnames: [api.example.com]
rules:
- matches: [{path: {type: PathPrefix, value: /catalog}}]
backendRefs: [{name: catalog, port: 8080}]
Add cert-manager's Certificate and the api-tls Secret in the Gateway namespace. Then require valid issuers, approved claims, and STRICT mTLS for sensitive services.
Diagnose and migrate without a big bang
Check Accepted, Programmed, and ResolvedRefs with kubectl describe gateway. Then check routes with kubectl describe httproute.
Verify endpoints with kubectl get endpoints. A 404 often means a wrong host, path, listener, or parentRef.
A 503 often means zero ready endpoints. It can also mean a wrong Service port or failed upstream policy.
Migrate one hostname or namespace at a time. Remove legacy resources only after traffic and error rates stay stable.
Do not add Istio only to publish a simple API with few services. This does not fit when you need no mTLS, traffic segments, distributed tracing, or Zero Trust policy. Also, do not replace dedicated API management when monetization, partner onboarding, a developer portal, or consumer analytics are primary needs.
Troubleshoot from route attachment to upstream. Do not change several policies at once.
Run kubectl get gateway,httproute -n store. Then run kubectl describe gateway public -n store.
Inspect Accepted, Programmed, and listener conditions. Next, inspect kubectl describe httproute catalog-route -n store.
Look for rejected parent references or backend references. Confirm selected Pods with kubectl get endpointslices -n store -l kubernetes.io/service-name=catalog.
Compare the Service port with the container port. A mismatch can cause a 503.
On the Istio gateway Pod, istioctl proxy-status shows stale or disconnected proxies. istioctl proxy-config routes <gateway-pod> -n <gateway-namespace> shows received hosts and routes.
Inspect kubectl logs <gateway-pod> -n <gateway-namespace> -c istio-proxy. Look for TLS handshake failures, upstream resets, or RBAC denials.
Migrate legacy Gateway and VirtualService resources after inventorying hosts, paths, subsets, rewrites, retries, faults, and bindings. Start with one hostname or low-risk path.
That path should map directly to a Kubernetes Gateway and HTTPRoute. Cross-namespace routes may need allowedRoutes and a ReferenceGrant.
Istio can run legacy traffic APIs and Gateway API during migration. Avoid two competing configurations on the same listener and host.
Compare route status, Envoy configuration, request logs, latency, and error rates. Do this before moving DNS or retiring a VirtualService.
Recreate security rules explicitly. A working HTTPRoute does not prove equivalent authentication, authorization, mTLS, or destination rules still exist.
What people ask
Can istio replace an API gateway?
Istio can handle routing, TLS, JWT checks, and traffic policy. It cannot replace portals, subscriptions, monetization, or consumer product analytics.
What is the difference between istio gateway and gateway API?
Istio Gateway is an Istio traffic resource. Kubernetes Gateway API is a routing standard that uses Gateway and HTTPRoute objects.
Istio can enforce Gateway API resources. The two can work together in the same cluster.
Why does my HTTPRoute return 503?
An HTTPRoute returns 503 when its backend Service has no reachable healthy endpoint. Check Pods, selectors, endpoints, and backendRefs.port.
A wrong target port can also cause 503. Check that the Service port maps to the container port.
Should internal services use the same API gateway?
Internal services should usually use Istio mTLS and AuthorizationPolicy, not a public API gateway. This avoids needless east-west hops.
Use an API gateway internally only when you need a real consumer API boundary. Examples include shared platform APIs or tenant-specific quotas.
Your next architecture decision
Choose the smallest set of layers that meets a real requirement. List every external consumer and each sensitive internal service.
Assign every control to one owner. Do not enforce the same rule in three places.
The essential points:- Gateway API defines public listeners and routes, while Istio protects service-to-service traffic.
- An Istio ingress gateway does not replace API products, consumer plans, portals, or monetization.
- Require HTTPS, caller identity, route authorization, mTLS, and workload authorization for sensitive paths.
- Debug 404 errors at route attachment and 503 errors at Service endpoints before changing policies.
- Migrate from VirtualService by hostname or namespace, with measured validation instead of a cluster-wide cutover.
Learn more
Here are some additional resources on this subject: