Did you know that you can navigate the posts by swiping left and right?

AWS API Gateway with internal alb ECS services

21 Mar 2018 . category: tutorial . Comments

I’ve recently came across an architecture which contained several microservices being contacted by AWS API Gateway. All of them were served behind an external alb on Amazon AWS. The problem here was that a lot of these microservices were mainly used for backed calls, there was no need for them to be exposed to the world.

The backend microservices were moved behind an internal ALB. This made sure that they could not be accessed from the world. The only way to access them is if you are in the VPC which they are deployed in.


Amazon API Gateway is deployed outside the VPC.

  • There is no option to deploy the API Gateway inside the the VPC.
  • API Gateway can not send requests to an internal ALB.

Possible Solutions

  1. Make the internal ALB an external ALB again
    • Not an option because then we would need to add extra security to each microservice.
  2. Use AWS Lambda as a proxy
    • Lambda can only pass json objects, we want more than that.
  3. Work with internal Network Load Balancers (NLB's) and put each service behind a port.
    • Really easy to mix something up here. You can have the correct URL, but with a wrong port which would call a different service than intended!
  4. Setup an HA Proxy cluster
    • HAProxy can run on the Elastic Container Service (ECS) cluster and use our existing Loadbalancers to forward to requests inside the VPC.


  • Seperate Route53 element (a .proxy endpoint. Example: service1.proxy.example.com) Which points to an external ALB

  • HAProxy service running on the ECS Cluster. make sure the HAProxy only accepts request from the API Gateway. Below is a small example of what your HAProxy config should contain. Change [APIID] and [ALB_IP_x] to the correct values.
    frontend http-in
        bind :80
        acl user_agent hdr_sub(User-Agent) -i AmazonAPIGateway_[APIID]
        block if !user_agent
        default_backend web-app-cluster
    backend web-app-cluster
        balance leastconn
        option httpclose
        cookie JSESSIONID prefix
        server node1 [ALB_IP_1]:80 check
        server node2 [ALB_IP_2]:80 check
        server node3 [ALB_IP_3]:80 check

  • Seperate TargetGroup which listens to the above endpoint and points to the HAProxy running on the ECS Cluster

  • HAProxy Forwards the request to the internal ALB

  • Seperate Listener Rule on the Internal ALB to listen to the Proxy endpoint (service1.proxy.example.com) and point to the Service Target group (Service1)

In the end, the architecture looks like this: stack

Request Cycle

An API request will roughly look like this:

  1. Client makes a call to the API Gateway
  2. API Gateway makes a call to the proxy endpoint, which is located at the external ALB
  3. The target group on the external ALB points to the HAProxy Service
  4. HAProxy service forwards the request to the internal ALB
  5. The target group of the internal ALB points to the correct microservice.


Thomas Van den Berge is a DevOps Cloud Engineer/Senior Backend Developer based in Belgium near the beautiful city of Ghent. In his spare time he likes to spend time with his daughter, work on his fishtanks and travel.