All Insights
Cloud & DevOps12 min read

API Gateway REST vs HTTP vs ALB vs NLB: Pick The Right Front Door

  • AWS
  • API Gateway
  • ALB
  • NLB
  • Architecture
API Gateway REST vs HTTP vs ALB vs NLB: Pick The Right Front Door

I have shipped APIs behind API Gateway REST, API Gateway HTTP, ALB, and NLB. The right answer depends on latency budget, request volume shape, auth model, and whether you need WebSockets or private integration. This is what has actually worked for us, with numbers and code you can lift.

What We Measured: Latency And Throughput

All tests were us east 1, cross AZ, warm paths, no CloudFront in front. Payloads were small JSON, ~1 KB, and targets were either Lambda or ECS on Fargate. Your numbers will vary, but the relative spread is consistent.

  • API Gateway HTTP to Lambda: 6 to 9 ms added p50 over direct ALB to the same backend. p90 12 to 18 ms. p99 25 to 40 ms. Lambda cold starts dominate if you do not keep it warm.
  • API Gateway REST to Lambda: 15 to 25 ms p50 overhead. p90 30 to 50 ms. p99 60 to 100 ms. REST has more features and more hops.
  • ALB to ECS: 1 to 3 ms p50. p90 4 to 7 ms. p99 8 to 15 ms. HTTP keep alive is critical to keep new connection rate low.
  • NLB to ECS: sub millisecond to 2 ms p50. p99 usually under 5 ms. This is L4, so you lose L7 features but you get the least overhead.

With CloudFront in front of HTTP APIs or ALB you will pay TLS handshakes at the edge once per connection and often shave a few ms on tail latency for global clients. For in region service to service calls, CloudFront rarely helps latency.

Cost Per Million Requests In Practice

Sticker prices as of this writing, in us east 1 ballpark. Always check the AWS pricing pages for your region before committing.

  • API Gateway HTTP: about $1.00 per million requests. WebSocket API has a different model, roughly $1.00 per million messages plus connection minutes.
  • API Gateway REST: about $3.50 per million requests. Feature rich but you pay for it.
  • ALB: charged per ALB hour plus Load Balancer Capacity Units per hour. 1 LCU covers 25 new connections per second, 3,000 active connections, 1 GB processed per hour, and 1,000 rule evaluations per second. LCU hours are cheap, the fixed hourly cost is what bites at low traffic.
  • NLB: similar to ALB with NLCUs, priced on new flows per second, active flows, bandwidth, and TLS processing if you terminate at NLB.

The only way to reason about ALB and NLB is by scenario.

Scenario A, steady 50 RPS API, 1 KB JSON, simple routing, good keep alive.

  • Data processed per hour ~180 MB, well under 1 GB per LCU. New connections per second are low with keep alive. Rule evaluations trivial. You sit under 1 LCU most hours.
  • Variable cost from LCUs works out to low cents per million. The dominant cost is the fixed per hour ALB charge while the load balancer is up. If you push a million requests in about 5.5 hours at 50 RPS, total ALB spend per million is around tens of cents. That is cheaper than API Gateway.

Scenario B, low trickle 1 RPS API, 1 KB JSON.

  • To hit a million requests you run the ALB for about 11.6 days. You still pay the per hour ALB charge. Your per million cost is several dollars. HTTP API at about a dollar per million is cheaper until your average RPS rises.

Scenario C, bursty traffic with thousands of new connections per second and large payloads.

  • LCUs climb quickly from the new connection component and bytes processed. At some point the LCU spend roughly equals or exceeds HTTP API spend. You would then compare against HTTP API while also looking at latency needs.

The rule of thumb we use:

  • Under a few sustained RPS and you want to keep ops simple, HTTP API wins on cost and simplicity.
  • Above a steady double digit RPS with small payloads, ALB wins on cost. NLB wins if you can live without L7 features.
  • REST API is always a premium. Only use it for features you can justify.

If cost modelling is fuzzy and you want a quick second set of eyes, we cover this kind of trade study in an architecture review or as part of API system integrations work.

Auth And Security That Actually Matter

API Gateway HTTP

  • JWT authorizers are first class. You can point at a JWKS URI from Cognito or any OIDC provider. Validation happens at the edge of the API, no code needed.
  • IAM auth works for service to service inside AWS with Signature V4. It is simple, fast, and auditable.
  • Custom authorizers are available if you have a weird edge case. Keep the Lambda fast or you will pay latency.
  • Mutual TLS on custom domains is supported if you need client certs.

API Gateway REST

  • All of the above, plus mature usage plans and API keys per method. You also get request validation, mapping templates, and stage variables. These add power and latency.

ALB

  • You can attach WAF to ALB and use managed rulesets and JWT inspection. WAF can validate a token signature against JWKS and enforce claim constraints. This has worked well for us when we wanted L7 enforcement without pushing auth into the app.
  • ALB listener rules support an authenticate OIDC action. It fits browser flows with redirects and cookies. For headless API to API JWT it is usually not what you want.
  • Client IP shows up in X Forwarded For. If you need mutual TLS, terminate at ALB with ACM and forward client cert details via headers to the app for verification.

NLB

  • L4 only. No WAF on NLB. If you need WAF, put CloudFront in front or terminate TLS at a reverse proxy behind NLB. You can still do mutual TLS at the target, and you get preserved source IP by default. Proxy Protocol v2 helps targets learn client details.

Both API Gateway and ALB can attach AWS WAF, which in practice is how we block obvious junk and enforce basic request size or rate limits before the app sees the traffic. We usually wire this as part of a broader cloud devops engagement so ops owns the knobs.

WebSockets, Streaming, And gRPC

  • WebSockets with serverless fanout: API Gateway WebSocket API is the easy button. It tracks connections and gives you a connection ID you can post to from Lambda or any backend. Cost model is messages plus connection minutes. We have run millions of concurrent minutes this way without drama.
  • WebSockets with stateful services: ALB supports WebSocket and HTTP 2 and can front ECS or EC2. For long lived connections and high throughput per connection we prefer ALB over API Gateway due to latency and cost.
  • gRPC: use ALB or NLB. ALB supports HTTP 2 with gRPC and gives you L7 routing. NLB works well if you want pure L4 and TLS pass through to gRPC servers that own certs.
  • Server Sent Events: ALB is fine. API Gateway default 29 to 30 second integration timeout can be a problem for long streams. There are ways around it with polling or chunking, but ALB is simpler.

Private And Hybrid Patterns

Private API exposed only inside VPCs

  • API Gateway private endpoint type restricts access to specific VPC interface endpoints. Add a resource policy to lock it to accounts and VPCs. Works well for shared services across accounts.

Private integration to VPC backends

  • Use API Gateway VPC Link to reach private NLB or ALB targets. HTTP API and REST both support VPC Link. We still bias to NLB targets for simplicity and throughput.

Ingress to private ECS or EKS from the internet

  • Put ALB public. If you must require IAM Signature V4 from clients, place API Gateway HTTP in front and integrate privately to NLB. That gives you IAM on the edge and private networking into the cluster.

Edge optimized or global

  • REST API has an edge optimized endpoint mode that deploys a managed CloudFront distribution. HTTP API is regional. If you want global acceleration with HTTP API or with ALB, place CloudFront yourself.

For a concrete example of ECS with API Gateway ingress and a load balancer, we published notes on the exact wiring in our write up on deploying ECS with API Gateway and a load balancer.

Operational Trade Offs And Limits

  • Timeouts: API Gateway has a hard 29 to 30 second integration timeout. If your backend needs longer, do not put it behind API Gateway unless you rework the call as async. ALB idle timeout is configurable, defaults to 60 seconds and can be increased a lot.
  • Payload limits: API Gateway caps payloads around 10 MB. ALB forwards streams, so the cap is really on your target and WAF limits. If you move large uploads, prefer ALB or pre signed S3.
  • Rate limits and quotas: API Gateway has per stage and per method throttling, burst and steady rates. There are regional account level soft limits you can raise. ALB has no per API quota. You enforce with WAF or in app.
  • Access logs: API Gateway logs to CloudWatch with detailed fields but there is a cost to verbosity. ALB and NLB access logs go to S3, cheap to keep and easy to Athena query.
  • Blue green and canaries: API Gateway stages and weighted routes make traffic splitting easy. ALB supports weighted target groups per rule. Both play well with scripted rollouts.
  • Multi account: API Gateway plus VPC Link and PrivateLink is the cleanest. ALB can be shared via AWS RAM but cross account TLS and WAF setup can be fiddly.

When To Choose Which

Pick API Gateway HTTP when

  • You want simple, low ops, IAM or JWT auth at the edge, and request rate is low to moderate. You do not need features unique to REST API.

Pick API Gateway REST when

  • You need request and response mapping templates, usage plans, API keys, request validation, or edge optimized endpoint without running your own CloudFront.

Pick ALB when

  • You run ECS, EKS, or EC2 and want low latency, L7 routing, WAF, WebSockets, or streaming without API Gateway limits. Cost wins at steady traffic.

Pick NLB when

  • You want the least latency, L4 only, gRPC with TLS pass through, or very high throughput per connection. You accept that auth and inspection move elsewhere.

If you are on the fence, a short architecture review with traffic shape and auth needs usually gets to an answer in under a day.

CDK Example: HTTP API With JWT And Private NLB

This is a minimal TypeScript CDK stack that creates:

  • A VPC with an internal NLB and target group.
  • An API Gateway HTTP API with a VpcLink private integration to the NLB.
  • A JWT authorizer that validates tokens from a JWKS URL.

Wire your ECS service or EC2 instances into the NLB target group. This pattern gives you IAM or JWT at the edge with private networking to your services.

import * as cdk from 'aws-cdk-lib';
import { Construct } from 'constructs';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as elbv2 from 'aws-cdk-lib/aws-elasticloadbalancingv2';
import * as apigwv2 from 'aws-cdk-lib/aws-apigatewayv2';
import * as apigwv2i from 'aws-cdk-lib/aws-apigatewayv2-integrations';
import * as apigwa from 'aws-cdk-lib/aws-apigatewayv2-authorizers';

export class HttpApiPrivateNlbStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const vpc = new ec2.Vpc(this, 'Vpc', {
      maxAzs: 2,
      natGateways: 1,
    });

    // Internal NLB
    const nlb = new elbv2.NetworkLoadBalancer(this, 'Nlb', {
      vpc,
      internetFacing: false,
      crossZoneEnabled: true,
    });

    // TCP target group on port 8080 for your ECS or EC2 targets
    const tg = new elbv2.NetworkTargetGroup(this, 'Targets', {
      vpc,
      port: 8080,
      protocol: elbv2.Protocol.TCP,
      targetType: elbv2.TargetType.IP, // use IP for ECS tasks
      healthCheck: { port: '8080' },
    });

    new elbv2.NetworkListener(this, 'Listener', {
      loadBalancer: nlb,
      port: 8080,
      defaultTargetGroups: [tg],
    });

    // VPC Link for private integration
    const vpcLink = new apigwv2.VpcLink(this, 'VpcLink', {
      vpc,
      // CDK will create the necessary NLB link
      // If using CDK v2 apigatewayv2, VpcLink integrations support NLB and ALB
    });

    // HTTP API with JWT authorizer
    const httpApi = new apigwv2.HttpApi(this, 'HttpApi', {
      apiName: 'private-nlb-http-api',
    });

    const jwtAuthorizer = new apigwa.HttpJwtAuthorizer('JwtAuth', {
      jwtAudience: ['your-audience'],
      jwtIssuer: 'https://your-issuer.example.com/', // OIDC issuer with JWKS
    });

    // Private integration to the NLB listener
    const integration = new apigwv2i.HttpNlbIntegration('NlbIntegration', nlb, {
      listener: nlb.listeners[0],
      vpcLink,
    });

    httpApi.addRoutes({
      path: '/api/{proxy+}',
      methods: [apigwv2.HttpMethod.ANY],
      integration,
      authorizer: jwtAuthorizer,
    });

    // Output invoke URL
    new cdk.CfnOutput(this, 'InvokeUrl', { value: httpApi.apiEndpoint });
  }
}

If you need a public ALB instead, swap the NLB for an ALB and use the HttpAlbIntegration. If you want IAM instead of JWT, change the authorizer to an IAM auth setting and sign requests with SigV4 from clients.

What We Would Do Differently Next Time

  • Do not assume REST API is the future proof default. We have migrated REST APIs to HTTP API to cut cost by 60 to 75 percent and save 10 ms per call without losing needed features.
  • Model LCUs early. A one hour Jupyter notebook that simulates connection reuse and payload sizes can change the decision. It has more impact than debating pros and cons.
  • Put WAF in front on day one. Even a bare managed ruleset cuts noise. Add JWT inspection if you terminate at ALB.
  • For private microservices, prefer HTTP API with VPC Link to NLB. It keeps auth and routing consistent and keeps the services private. When we tried to reuse a public ALB for internal traffic we paid later in policy sprawl.
  • Keep a path to both. If you are unsure, wire both an ALB and an HTTP API to the same backend and flip clients by DNS or feature flag. That reduces the pressure to predict the future perfectly.

If you want a second set of hands to design or implement the ingress layer cleanly, that is the kind of build we run in our API system integrations projects. We get it deployed, instrumented, and handed over with clear guardrails.

Techlusion
TechlusionAI-native product engineering partner
Share

Need help with Cloud & DevOps?

Talk to Khelan, Founder & CTO, about cloud & devops on a free 45-minute call.

Book Your Free Call