DEV Community

Cover image for API Gateways vs Service Meshes for .NET Microservices: Deployment
Amitesh0512
Amitesh0512

Posted on Originally published at amiteshsurwar.com

API Gateways vs Service Meshes for .NET Microservices: Deployment

Quick Answer

Explore the real engineering trade‑offs of API Gateways vs Service Meshes for .NET Microservices, with production patterns, performance numbers, and a decision matrix for Azure, Istio, Linkerd and more.

API Gateways vs Service Meshes for .NET Microservices – A Practical Decision Guide

Problem Framing – Why Traffic Management Breaks at Scale in .NET Microservices

In a production .NET microservice landscape, the first thing that breaks is the assumption that a single ingress component can handle both external client traffic and internal service‑to‑service concerns. Teams often start with an API gateway for .NET because it offers a familiar entry point, but as the mesh of services grows, latency spikes, policy drift, and operational toil explode. The core question is: API Gateways vs Service Meshes for .NET Microservices. The answer is not binary; it is a layered decision that depends on traffic patterns, compliance needs, and team skill sets.

Real‑World Example – FinTechX’s 5‑Service Payment Platform

FinTechX runs a payment platform that exposes five ASP.NET Core services: Auth, Orders, Payments, Fraud, and Analytics. The platform serves ~12k requests per second from a mix of web, mobile, and partner APIs. The initial rollout used Azure-ai-foundry-vs-azure-openai-service-observability-in-production-20261007" class="internal-link">Azure API Management (APIM) as the sole gateway, with all internal calls routed through the same ingress. Within weeks the team observed:

  • 99th‑percentile latency grew from 30 ms to 120 ms as the number of services hit 10.
  • Policy drift: the Fraud service started bypassing authentication because the gateway had a stale cache entry.
  • Operational toil: every new service required manual APIM policy updates, and developers complained that the gateway added a 2‑ms overhead per call.

After adding Istio sidecars to the cluster, the latency dropped to 35 ms on average, and the team gained fine‑grained traffic routing without code changes. This case study illustrates the practical trade‑offs that drive the decision.

Trade‑offs – API Gateway vs Service Mesh

  • Latency: APIM adds 1–3 ms TLS termination and policy evaluation; Istio sidecar adds 2–4 ms for mTLS handshake on the first request. In high‑frequency loops, the mesh overhead is negligible compared to the 10–20 ms gained from removing gateway hops.
  • Operational Complexity: APIM is a managed service; Istio requires a control plane and sidecar injection pipelines. Teams that already own an Azure DevOps CI/CD pipeline can automate sidecar injection with kustomize, but the learning curve remains steep.
  • Policy Granularity: Gateways enforce client‑level rules (API keys, OAuth scopes). Meshes enforce service‑level rules (mTLS, RBAC between services). Mixing them without a clear boundary leads to duplicate enforcement.
  • Observability: APIM exposes request counts, latencies, and quota usage; Istio exports distributed traces and per‑service SLO metrics. Relying on APIM telemetry alone hides intra‑service latency spikes.
  • Security & Compliance: APIM handles external compliance (e.g., PCI‑DSS). Istio provides end‑to‑end encryption and fine‑grained access control. If your regulator requires audit trails for every hop, you need both.
  • Cost: APIM is billed per unit (~US$2.5k/month for Premium). Istio sidecars add ~0.1 vCPU per pod; in a 50‑service cluster that’s ~25 vCPU (~US$300/month on AKS). The cost differential is negligible compared to the resilience benefits.

Decision Guide – When to Use Which Layer

Scenario Recommended Stack Key Decision Points
Low traffic (<1 M req/day), minimal compliance, tight dev cycle APIM only Latency budget >200 ms, team prefers managed service
High traffic (>5 M req/day), multiple regions, complex routing APIM + Istio (or Linkerd) Need per‑service retries, traffic splitting, and mTLS
Regulated industry, strict audit, end‑to‑end encryption APIM + Istio + Azure Monitor Audit log per hop, strict compliance, high SLA
Serverless first, minimal infra management Azure Functions + Linkerd Low overhead, keep serverless latency <30 ms

When This Fails in Production

  • Traffic Spike & Sidecar Cold Start: A sudden surge of 30k req/s can overwhelm the control plane, causing sidecar injection delays and increased latency until the mesh stabilises.
  • TLS Termination Misconfiguration: If APIM is configured to pass through TLS to the cluster but the services expect mTLS, you get handshake failures and 502 errors.
  • Policy Drift Between Layers: Duplicate rate limits can cause unexpected throttling when a request passes through both APIM and the mesh.
  • Sidecar CPU Exhaustion: In a dense pod schedule, each Envoy sidecar can consume ~50 mCPU; in a 200‑service cluster this adds >10 vCPU, leading to OOM kills.

Common Mistakes Engineers Make

  • Using the gateway for internal traffic – this doubles the hop count and introduces unnecessary latency.
  • Neglecting to propagate the sub claim from APIM into the X-Caller-ID header – downstream services lose identity context.
  • Assuming the mesh will automatically enforce quotas – it only enforces per‑service limits unless you explicitly configure EnvoyRateLimitService.
  • Deploying Istio without enabling autoInject – some pods bypass the sidecar, breaking mTLS.
  • Ignoring the impact of sidecar memory usage on autoscaling – pods may scale up too aggressively, creating a feedback loop.

Better Approach Based on Experience

In production, we adopt a two‑layered traffic plane:

  • Edge Layer – APIM: Handles TLS termination, OAuth, API‑key validation, request shaping, and global rate limits. We keep policy logic in reusable policy.xml files and avoid embedding business logic.
  • Mesh Layer – Istio (or Linkerd): Manages mTLS, retries, timeout budgets, traffic splitting, and distributed tracing. All services expose a service‑account identity; Istio enforces AuthorizationPolicy objects that map service accounts to allowed targets.
  • Observability Stack: We ship OpenTelemetry traces to Azure Monitor and Prometheus. The mesh exports istio_requests_total and istio_request_duration_seconds, which we aggregate into Grafana dashboards. APIM metrics feed into Azure Sentinel for anomaly detection.

This pattern keeps the gateway focused on client concerns and the mesh on inter‑service resilience. It also simplifies troubleshooting: a 5xx from a downstream service is always traceable to a sidecar, not buried in gateway logs.

Performance Considerations & Scaling Notes

  • Latency Budget: For a 30 ms SLA, the combined APIM (1–2 ms) + sidecar (2–4 ms) + service (5–10 ms) stays comfortably under budget. The critical path is the first request to a service after a sidecar restart, which can add 5–10 ms for mTLS handshake.
  • CPU Overhead: Envoy consumes ~30–50 mCPU per pod; Linkerd is ~10 mCPU. In a 100‑pod cluster, this adds 3–5 vCPU – negligible compared to the cost of an APIM Premium unit.
  • Autoscaling: Configure HorizontalPodAutoscaler on both services and sidecars. Ensure the sidecar’s --proxy-resources flag is tuned to avoid memory contention.
  • Control Plane Scaling: Istio Pilot can become a bottleneck; upgrade to a dedicated control plane node pool with 4 vCPU and 16 GiB RAM if you exceed 50 services.
  • Network Egress: APIM is a public endpoint; use VNet integration to keep traffic within Azure. For cross‑region traffic, use Azure Front Door to route to the nearest APIM instance.

What to Ship

  • Map each service’s traffic profile and decide: external-facing services go through the API gateway, while internal services communicate via the service mesh. Document the mapping in a shared architecture diagram.
  • Configure the API gateway with authentication, rate‑limiting, and request shaping rules; configure the service mesh with mutual TLS, circuit breakers, and traffic mirroring for intra‑service calls.
  • Centralize routing and policy definitions in a single config repository, then deploy gateway and mesh configs from the same CI pipeline to avoid drift.
  • Enable sidecar injection and enforce mTLS for every microservice so that all internal traffic is encrypted and authenticated.
  • Define a fallback routing rule in the gateway that automatically redirects traffic to a degraded service or a static response if the service mesh reports health failures.
  • Add automated integration tests that exercise both gateway and mesh paths, and trigger a canary release that gradually shifts traffic while monitoring latency and error rates.

Conclusion

The choice between an API gateway and a service mesh is not a binary one; it is a layered decision that must be tuned to traffic volume, compliance mandates, and operational maturity. By keeping the edge and the mesh orthogonal, you avoid duplication of policy enforcement, keep latency under control, and gain the observability needed to run a resilient .NET microservice platform at scale.

Related Articles

Top comments (0)