An independent guide to building modern software for serverless and native cloud

Understanding API Gateway

Where the last two sections on CloudFormation and CloudWatch were about tools, this section is the first of three that will cover working with serverless building blocks. And of these three building blocks, API Gateway is the most important because it shapes the architectures you can apply in the layers both above and below it.

Choosing Between REST & HTTP Versions

Before starting, we should note that the API Gateway service is currently offered in two different versions that, confusingly, have overlapping features. The “HTTP” version of the service is simpler, cheaper, offers higher performance, and contrary to the name, does let you implement REST APIs. It also integrates with open authentication standards like OAuth 2.0 as opposed to just the in-house AWS Cognito service. However, only the “REST” version of API Gateway has full support for importing OpenAPI specifications, and for API management tools like usage plans and API keys. These features are key to supporting the full range of usage scenarios that we care about. And so this is the version that we cover in this course and that you’ll see defined in templates in the sample code.

Working with Cloud Native

A lot of traditional web applications handle request routing, validation, and authorization within application code. API Gateway demonstrates the benefits of working with a cloud native service. With API Gateway you’re moving everything except the actual processing of requests out of your application code and into a zero-maintenance, automatically scaled, fully managed cloud service. This service can be deployed and monitored using the native CloudFormation and CloudWatch tools we’ve just covered. It also natively integrates with the AWS networking and security infrastructure, enabling private and hybrid cloud integrations.

Working with Modern API Standards

You build APIs to give client applications access to data or services. Historically, there have been a series of technologies and standards for doing this, progressing in my own career, from Corba, to Java RMI, through to .Net WCF and SOAP. Today, the industry has coalesced around the REST standard, and for good reasons. With REST you’re leveraging proven, workable web technologies like HTTP and JSON, for which there’s a huge ecosystem of tools and services.

REST APIs are also stateless, which makes them inherently scalable, and guides API designers away from the kind of conversational interfaces that can leave systems in unstable states when they fail. Further, by adopting standard HTTP actions and request/response patterns, the REST standard inherently leads to a separation of commands from queries (GET vs PUT/POST/DELETE) and a separation of those updates that are idempotent from those that are not (PUT vs POST). In short, following REST principles leads to better system interfaces that are easier to debug, more scalable, and lend themselves more readily to service composition.

As noted above, the other API standard that the “REST” version of API Gateway supports is OpenAPI. If you’ve ever had to work with earlier standards like XML Schemas or WSDL, then you’ll find OpenAPI to be an evolutionary leap forward. Using OpenAPI you can start with schemas, defining enumerated or regex-constrained data fields, and then incorporate these fields into data objects. You can then define the resource paths and actions for your APIs, applying the field- and object-level schemas to parameters and request/response bodies. At each step, it’s worth noting, these definitions are written in easily read YAML format.

This ease-of-use makes the API-first approach practical. With this approach you design your system interactions in detail with OpenAPI, and then use tools to generate API documentation, test scripts and skeleton code. And, of course, once you’ve deployed OpenAPI-defined APIs to API Gateway, the schemas you’ve define are translated into model constructs that enable API-level request validation.

Enabling Modern Service Architectures

An API management service like API Gateway moves orthogonal concerns like request validation and authorization out of your application code and into a managed service. It makes it possible to manage access for third party applications, with individualized usage plans and API keys. It also provides a unified point of entry for those applications, enabling requests to be routed to multiple back-end services. Using API Gateway as a facade in this way enables a key element of modern service architecture: the factoring of backend code into micro-services.

Micro-services are a key element of modern service architectures for two reasons. First, factoring a large code base into smaller units forces you to surface and document the interactions between these units. Instead of having a web of undocumented, ad-hoc interdependencies within an unbounded, monolithic code base, micro-services lead to service interdependencies that are well defined and less tightly coupled.

Second, factoring code into separate micro-services makes it possible to implement those services with different technologies, and to deploy these services independently. So, if one service can best be built with a language or platform that’s different than the rest, micro-service architecture gives you have that option. Likewise, if one service needs to be updated out of sync with the others, you have the freedom to do that as well.

One architecture option that API Gateway potentially enables is the packaging of any part of your services code as Lambdas, or containers, or a mix of both. You could, for example, start off with an entirely serverless architecture like the one covered in this course, incorporating API Gateway and Lambdas, like this:

Once the above architecture is in production, you might find that some of the limitations inherent to Lambdas don’t fit your use cases. At that point you could switch the backend technology without impacting your client application in any way. An alternative architecture using containers, as shown below, is one to which you could seamlessly transition:

To summarize, API Gateway bridges your client applications and your backend services, making it possible to factor those services independently of how the of API endpoints are packaged. API Gateway can integrate natively with services like Lambda, and it can integrate with generic REST endpoints, which is how you can pass API calls through to containers, as shown above. Ultimately, the benefit of using an API management service like API Gateway is that you gain a lot of flexibility in the backend service architectures that you can adopt. This flexibility, in turn, buys you a lot of agility, because the impact of changes in the backend can more easily be isolated from the client applications.

Enabling Modern Application Architectures

API Gateway doesn’t just enable new downstream service architectures. When used in combination with an identity service like AWS Cognito, it also opens up new architecture possibilities for the applications that are upstream of your APIs. Let’s outline the component parts at work here, and then show how these can be used in different ways.

What you’re seeing in the concept diagram above is an example API used by both a web application and mobile app, where user authentication and authorization is delegated to Cognito. In this example, the web application uses the OAuth 2.0 Authorization Code Flow to enable users to authenticate. With this flow, when users sign in they are redirected to a Cognito-hosted login page, and are then redirected back once authenticated. The mobile app, as shown in the diagram, uses a native SDK to authenticate users through a direct call to the Cognito API.

In both cases, once a user is authenticated, the applications they’re using will have obtained an access token. Each subsequent client call to API Gateway will then include this token, which will be used to authorize these calls through an integration with Cognito. Note that in the diagram above, both applications are sharing an app client, which determines the identity sources, auth flows, and client credentials that are used. More on this shortly. (There’s a lot of details that we’ll glossing over here, but we’ll cover these details in depth in the lessons that follow.)

Even if you don’t take advantage of some of the architecture options we’re about to step through, there are benefits to delegating identity to a service like Cognito. To start, like API Gateway, Cognito is a managed service that requires no maintenance, scales automatically, and integrates natively with all the AWS network and monitoring infrastructure. I would argue that this is also a class of service that you don’t want to run yourself because of the burden of keeping up with an ever-shifting threat landscape.

Now let’s look at some of the frontend architecture options that are enabled with API Gateway and Cognito. Note that many of these options can be used in combination. You can:

  • Share the Cognito User Pool with multiple first-party applications, enabling users to login to these applications with the same credentials.
  • Share the Cognito User Pool and app client with multiple first-party applications, enabling users to extend their session boundaries across them without requiring authentication.
  • Allow access to multiple internal or external APIs from various applications, including those from third parties.
  • Allow external identity providers to federate with Cognito, enabling inbound users to login with their existing credentials.
  • Allow Cognito to federate with external identity providers, enabling outbound users to login to external services with their existing credentials. *

Be aware that Cognito doesn’t currently support outbound SAML integrations

What these API and identity service options enable, in the end, are modern user experiences. In today’s world, users expect to be able to use one set of credentials for related applications. They also expect to be able to use different platforms and devices to access services, like browsers on the desktop and mobile apps. Lastly, users don’t need or want to know about the application silos within an organization. They expect to perform tasks by seamlessly navigating across applications without the friction of repeated authentication steps.

Highlighting Limitations

As always, before moving on we should highlight some important limitations with the API Gateway service. First, there are account- and region-level quotas that apply to things like the number of API instances and custom domain names you can deploy, and the volume of requests your APIs can process. Check the documentation for details, and be aware that some of these quotas can be increased through AWS support. Second, there are hard limits for HTTP requests of 10MB in size and 30 seconds in processing time. If your use case will exceed these limits, then you will have to look at alternate technologies.