All articles
24 September 2026
10 min read

API Gateway or Application Load Balancer? What does a normal API on AWS need?

By Tim Rutte, Cloud & Software ArchitectTopicAWS & Cloud

On the left a Y-shaped junction of brushed steel pipe, on the right a white turnstile with three arms, one of them blue.

If an HTTP service on AWS is to be publicly reachable, you quickly end up at a seemingly simple question: API Gateway or Application Load Balancer?

My default is not automatically API Gateway just because the name says "API". If a normal HTTP service runs behind the endpoint on ECS, EKS or EC2, and what I mainly need is routing, TLS and load balancing, I start with an Application Load Balancer. I choose API Gateway when the API itself becomes the product or the control boundary: when I do not just want to forward HTTP, but deliberately need authorization, throttling, usage rules, API keys, validation or different backends on that layer.

Both can do HTTP. The more important question is therefore: do I need a load balancer in front of my application, or an API management layer in front of my clients?

An ALB is more than a distributor

The Application Load Balancer is sometimes portrayed as if all it could do is spread traffic evenly across servers. That picture is quite incomplete. An ALB distributes HTTP and HTTPS using listener rules, by host, path, header or method, across different target groups:

api.example.com/orders/*    -> Orders Service
api.example.com/users/*     -> User Service
admin.example.com/*         -> Admin Service

Targets can be ECS tasks, EC2 instances, IP addresses or Lambda functions. Authentication is not beyond it either: an ALB can sign users in via OpenID Connect or Amazon Cognito before a request reaches the application.

For many classic applications that already covers a great deal. I like to start architecture with the smallest layer that is sufficient, and if internet, HTTPS, ALB and ECS service are enough, I want to be able to explain why another API layer should sit in front of it.

API Gateway solves a different problem

API Gateway can forward requests to backends too, but that is only part of its model. It treats an API as a managed interface, with features for authorization, throttling, request handling, API management and integrations with other AWS services.

AWS distinguishes two kinds. HTTP APIs are the leaner, cheaper variant, with JWT, IAM and Lambda authorizers and throttling per stage and route. REST APIs offer full API management: API keys, usage plans with per-client limits, request validation against a schema, request and response transformation and direct integration with AWS WAF.

So even "API Gateway" is not a single architectural decision. Before I choose between ALB and API Gateway, I need to know which gateway features I actually need, and that often already settles which of the two kinds it would be.

For a normal ECS service, an ALB is enough

Take a backend made of a Go API on ECS Fargate, PostgreSQL and Redis, reachable at https://api.example.com. The service authenticates its users itself and scales horizontally. What is needed: TLS, health checks, routing, load balancing and deployments without downtime. My first architecture would be:

Route 53
   |
  ALB
   |
ECS Service
   |
Fargate Tasks

What would API Gateway additionally solve here? "It is an API" is not enough of an answer for me. I would have another component in the request path, more configuration and another place I have to understand when it comes to errors and cost. An additional layer has to take on an additional job, otherwise I leave it out.

An ALB fits exactly this kind of service: it runs permanently, has an HTTP port and a health check, and several tasks should receive traffic. That applies to a Go API just as much as to a PHP application, a Java backend or a Node service. Then there is a practical point often missing from comparisons: API Gateway limits a request to a 10 MB payload and the wait for the backend to around 30 seconds. Large uploads, long reports or streaming fit better behind an ALB, which does not set these limits in the same way.

Why the service underneath runs on ECS Fargate rather than Kubernetes is covered in ECS Fargate or Kubernetes.

When the interface itself gets rules

Now we change the example. The same API is used by 50 external customers. One may send 100 requests per second, another 1,000. There should be usage plans, maybe API keys, maybe different authorization models, and requests should be limited before they reach the application.

Now the API is no longer just an HTTP entry point but a product with rules. The architecture can then look like this, or, depending on the backend, with Lambda, an AWS service or a private integration via a VPC link instead of the ALB:

Clients
   |
API Gateway
   |
  ALB
   |
ECS Services

Now API Gateway pays for its place in the request path. It takes on responsibility that I would otherwise have to build myself in several applications.

Throttling is the best example of this, because the word hides two different problems. If I want to protect my infrastructure from overload, I have many levels: auto scaling, limits in the application, WAF rules, backpressure, queues, deliberately set capacity limits. For that I do not automatically need API Gateway. A rule per customer is something else:

/orders:     at most X requests per second      protecting the backend

Customer A:  100 requests per second            part of the product
Customer B:  500 requests per second
Customer C:  2,000 requests per second

An HTTP API can represent the first line per route. The second needs usage plans, and those exist only for REST APIs. If such rules are part of my API product, API Gateway comes into consideration very quickly.

Authentication alone does not decide it

Authentication used to be a clearer argument for API Gateway. Today HTTP APIs support JWT, IAM and Lambda authorizers, REST APIs even more extensive models, and at the same time an ALB signs users in via OIDC or Cognito. "We need a login" is therefore not a sufficient argument.

Instead I ask: what kind of identity are we protecting? For an internal web application behind a central OIDC provider, signing in at the ALB can be very elegant. For a public developer API with tokens, different clients, scopes, usage rules and a clear lifecycle, API Gateway fits much better. Again it is not the single feature that decides, but the context.

Lambda and different backends

It is different when there is no single HTTP service behind the API at all. POST /invoice leads to one Lambda function, GET /report to another, and POST /events writes straight into an AWS service or goes to a private backend:

                          /invoice -> Lambda
                        /
Client -> API Gateway ----- /users   -> service in the VPC
                        \
                          /events  -> AWS integration

Here API Gateway does more than a load balancer. It represents the API as an architectural component of its own in front of several different backends, and that is a strong use case.

"Serverless" alone is still not a reason for me, because an ALB can use Lambda functions as targets too. For APIs that consist mainly of Lambda functions I still check API Gateway first, because the API model, authorization, routing and integration usually fit together more naturally there. Feature lists alone do not settle it, since both can partly do the same things. The question is: which operating model represents my architecture more naturally?

Routing and transformation are not reasons in themselves

Distributing three paths such as /api/users/*, /api/orders/* and /api/payments/* across three services is something an ALB does very well. If routing is my only problem, I stay with the ALB. API Gateway comes in when the routing layer is also supposed to own things like API-specific authorization, per-client throttling, usage rules, API keys, request validation, a lifecycle of its own or different kinds of backends.

With request and response transformation I am more careful. If my gateway needs ten transformations because the backend has a bad interface, I may only have moved the problem, and I end up with three models instead of one: the client's, the gateway's and the backend's. Sometimes that is exactly right, for example when an existing legacy API cannot be changed and a stable public interface is supposed to sit in front of it. Then the gateway acts as an anti-corruption layer. With a new system I first check whether the API itself can become cleaner. A gateway takes on infrastructure and API responsibility, not business logic.

How a stable interface is put in front of a legacy system without the logic moving into the gateway is covered in Putting an API in front of the monolith.

Cost and what already exists decide too

API Gateway and ALB have different pricing models: API Gateway charges per request, the ALB per hour and by consumed capacity units. Which one is cheaper therefore depends on the load profile, on the number of requests, the data volume, how long connections last, the gateway type and the features used. Rules like "an ALB is always cheaper" or "API Gateway is cheaper for small APIs" may hold for a specific profile, but as a general rule they are too simple for me. I calculate with the real load: requests per month, average payload, peaks per second, number of services, and whether an ALB already exists.

That last point changes the decision the most. If an ALB already runs in front of services A, B and C and service D is added, the question is no longer "ALB or API Gateway from scratch?". Routing, TLS, monitoring, security groups, deployment and operating experience are already there, and the effort for one more service is small. Existing infrastructure is part of the decision.

The same applies the other way round. If an organization already has a central API platform with its own domains, authorizers, logging, policies, developer portal and usage plans, a single ALB endpoint for a new service would be the special path, even if it is simpler on its own. So I do not optimize for which service is simpler in theory, but for which solution creates the least additional complexity in this organization.

Outside and inside, and not every layer in front of every other

A public API for customers or partners has different requirements from an internal interface. Outside I care about quotas, client identity, scopes, versioning, documentation, abuse protection, onboarding and usage plans. Inside, more about latency, availability, networking, service discovery, authentication between workloads and observability. The same organization can therefore sensibly use both:

External clients
      |
 API Gateway
      |
     ALB
      |
+-----+-----+
|           |
Orders   Payments

Internally the services talk directly or via an internal load balancer. That is not duplication; they are two boundaries with different jobs.

The same split between the public and the internal boundary also carries the choice of protocol: REST or gRPC for backend services?

What I do not do: put API Gateway in front of every ALB by reflex. A standard architecture of CloudFront, API Gateway, ALB and ECS, plus WAF, is quickly built, and each component can be justified on its own. The problem starts when nobody asks any more which of them this application needs. Every network layer brings configuration, cost, limits, logs, failure modes, latency and deployment dependencies. Each layer may be cheap and reliable; the whole can still become needlessly complicated.

So I work through such designs backwards: which responsibility does this layer own? If I cannot answer that for a component, I take it out in my head and check what is then missing. If nothing is missing, it was probably not needed.

What I start with, and when

With an ALB when a classic HTTP service on ECS, EKS or EC2 sits behind it, I mainly need TLS, routing, health checks and load balancing, the application owns its API rules itself, an ALB is already running and the API is part of the application rather than a product of its own. Typical: a SaaS backend in Go on ECS Fargate, ten million requests a month, JWT validation in the service, one public frontend.

With API Gateway when external customers or partners use the API, authorization is to be enforced centrally, throttling or usage rules are part of the product, different backends come together under one API, Lambda or AWS integrations play a large role, the interface has a lifecycle of its own, validation or transformation is meant to happen at the gateway, or a central API platform already exists. Typical: a partner API with a hundred external integrations, different limits, several backends of Lambda and ECS and versioning of its own.

QuestionApplication Load BalancerAPI Gateway
Classic HTTP service on ECS or EC2usually my defaultpossible
Routing by path or hosta very good fitalso possible
Load balancing across several taskscore jobvia the backend integration
Lambdapossiblevery natural integration
Sign-in via OIDC or Cognitopossibleextensive authorization options
JWT authorizationrather in the applicationJWT authorizers on HTTP APIs
Usage plans and API keys per clientnoREST APIs
API-specific throttlinglimitedstronger
Request validation and transformationhardlymuch stronger
Large payloads, long requestswithout these limits10 MB, around 30 seconds
Several different backend typespossible, not the main modelstrong
Existing ECS platformoften very sensiblean extra layer
API as a product of its ownpossible, much built by handthis is where it shines
Smallest possible HTTP stackadvantageextra abstraction

The question I start with

When someone says "an API belongs behind API Gateway", I ask: which job does API Gateway take on here that is not already solved sensibly? If the answer is "per-client limits, authorization and one consistent external API in front of several backends", good, then it solves a problem. If it is "because it is an API", that is not enough for me. Equally, "an ALB is simpler" is no reason if what we actually have is an API management problem. The architecture should make the problem visible.

For a normal HTTP application on ECS or EC2 I therefore usually start with an Application Load Balancer. It takes on exactly the jobs I need there: TLS, routing, health checks, load balancing and the connection to the running services. I put API Gateway in front of it, or use it instead, when the interface itself takes on responsibility: when I have to manage clients, enforce API rules centrally or bring several different backends together under one API, or when the API becomes a product of its own. Then the extra layer is not ballast; it is architecture.

An HTTP service does not automatically need an API gateway. A real API platform usually needs more than a load balancer.

If you are facing this decision right now, the approach is described on the page for AWS migration.