Bringing server and server-less together with AWS API Gateway

Balu Vyamajala

Balu Vyamajala

- Principal Software Engineer

In most micro-service architectures, applications are broken down into multiple small apis which fall into two categories: server or server-less. This blog is about how we serve such content with web apps using AWS services.

Going fully server-less is not always going to be practical

Why not server-less for everything?

My choice is always ‘Go Server-Less’ unless one of the below criteria is met.

  • Total Run time: An api is heavily used and is constantly running for more than 50% of the time, setting up a server might actually save some cost.
  • Development Time: Imagine building CRUD APIs for a bunch of tables with a framework like Spring Boot vs building multiple NodeJs Lambdas for each table. Time needed on the former is just 10% of time needed for development and Dev-Ops of the later. Setting up a single small server on Fargate is a far easier choice.
  • Datastore type: Managing Transmission Control Protocol (TCP) connection pools to relational database in server-less might get tricky and will overhead to API performance especially when running Lambdas within Virtual Private Cloud (VPC) to be able to connect to private Relational Database Service (RDS) or on-prem.

So most of the times we end up having a mix of server and server-less.

Imagine we have a relation database running in RDS in a private subnet in our VPC and we need a bunch of APIs to be exposed with a combination of server and server-less. Let’s put together an architecture.

Server-less APIs

AWS Lambda functions:

  • I typically choose a simple NodeJS instead of heavy framework with Java to reduce startup time.
  • We can run Lambdas within VPC to be able to connect to RDS privately.

Server APIs

Java Spring boot:

  • The simplest choice in my opinion for exposing Rest APIs built as a Docker container deployed to AWS ECS Fargate.
  • With servers we need to handle scaling, health checks, and monitoring CPU usage, etc.
  • Setting up an AWS ELB to redirect requests to a healthy task.
  • This can be an internal LB as requests will not be directly from the internet but only from Gateway.

Gateway

Public facing AWS Api Gateway to expose APIs from both Lambdas and Fargate.

  • Choose a prefix for Fargate APIs and another prefix for APIs from Lambda. For example /server and /serverLess.
  • Any API prefix with /server/** should be proxied to ELB while all other endpoints will be sent to individual Lambdas.

API Gateway to Private Elastic Load Balancing (ELB)

  • Integration from AWS API Gateway to a private ELB can only be done to a Network Load Balancer (NLB).
  • We must create a VPC link to NLB and redirect /server/{proxy+} to nlb-dns-name/{proxy} via Integration type ‘VPC Link’.
  • We don’t need Transport Layer Security (TLS) Termination at NLB, instead an API Gateway will terminate and initiate a new connection to NLB, which is simply passed to Fargate services.

Offloading security outside application code is always a better choice.

API Security

  • Likely to get a Bearer Token like a JSON Web Token (JWT) for most of the Authentication types. It is best to offload activities like token validation and parsing outside the application code instead of implementing something like Spring Security within server code.
  • We can go with AWS API Gateway Custom Authorizer to validate the token, and set context attributes to pass ID information as http headers.
  • The same custom authorizer works for both server and server-less endpoints.

Architecture