The “API Gateway-first approach” is the idea that, in the context of an AWS
cloud stack, when we build a new service, we first consider using
API Gateway. If it doesn’t fit our use
case, we can consider something else, such as a
load balancer in front of a
Node.js server running on Fargate.
API gateway is a powerful service and by far my favorite of the AWS ecosystem.
It is the glue that connects a web request to another AWS service—like Lambda or
DynamoDB—which gives us the ability to take granular design decisions for each
endpoint of our service. It helps us define strict boundaries in our code to
leave the orchestration code out of our business logic code—handled in a Lambda,
for example.
If you are used to building Node.js microservices, you can see API Gateway as
the combination of a load balancer and a routing system
(express router or
koa router).
What I like about API Gateway:
- AWS fully manages it, so we don’t need to handle its availability, and we can
set it up using CloudFormation (CDK).
- We can collocate different stacks under the same domain. For instance, we can
run a React application (Fargate) alongside a REST API (Lambda + DynamoDB).
That allows us to choose different solutions depending on the endpoint’s need.
Therefore it will be easier to maintain the service over time because we can
replace components separately. It is worth noting that API Gateway can proxy
to different types of AWS services, so we don’t necessarily need to use a
Lambda. A rule of thumbs is that if the Lambda is only responsible for passing
data from one service to another, it’s a sign that we can use an API Gateway
integration. For instance, we can directly map a request coming through API
Gateway to
DynamoDB using mapping templates.
- We can scale at the endpoint level instead of at the service level. However,
like any serverless service, we can’t scale indefinitely—we need to consider
the API Gateway request per second limit and concurrency burst limit.
- We can grant different permissions for each endpoint to reduce the blast
radius if the service is compromised (following
the least privilege principle).
- It’s the perfect candidate to apply the
strangler pattern
for migrating a legacy application to a new stack. When we start the
migration, API Gateway will proxy all queries to the legacy service. Piece by
piece, we can migrate each endpoint individually to point to a new
integration.
- There is integrated support with CloudFront (for caching and running our
service at the edge) and CloudWatch (to track errors and other metrics), so it
is easier to set up, and we have less boilerplate code.
However, API Gateway is not a silver bullet and has some limitations. Remember
that it is a “first approach,” not an “only approach.” Drawbacks of API Gateway:
- It connects different services with their limitation (API throttling, timeout,
etc.), impacting performances or leading to failure. When designing a system,
we also need to take them into account.
- Since each endpoint can be a different integration, it makes testing more
challenging. For instance, if we use API Gateway + DynamoDB we cannot run it
locally. We need to deploy a test stack against which we run our tests
(end-to-end tests). It gets slow to run on a CI because deploying and
destroying a stack takes several minutes. Some solutions, like
LocalStack, can mock different AWS
services locally, which will reduce the time to run the tests, but we lose the
benefits of testing against the real environment.
- The possibility to use a mapping template to transform the data from API
Gateway to another service is excellent in theory. Because it removes the need
to build and monitor another Lambda, and we leave it to AWS to fully handle
the transaction. However, the template language can be tricky to use and
debug. Since we are writing a string, our editor has no support to help us
figure out what data we’re handling. The only source of information is the
documentation
page. So, the learning curve can be steep, and depending on your needs, it
might be simpler to use a Lambda.
Next time you start to build a new service before jumping on Node.js, Express,
and Docker, think about it, can you use API Gateway instead?