There are many use-cases where a serverless architecture has a lot of benefits and of course an API service is not the exception. In a previous post, we learned how to deploy a Flask application on EC2 using a Load Balancer and Auto Scaling Groups. Of course, you can think about deploying it into the AWS Elastic Container Service but…, what if you don’t want to manage instances or clusters?

The first piece of advice we can give you is that you should not architect differently for serverless because you should be able to deploy your service in different environments without code modifications…

Architecture

The entry point for our Lambda Function where our FastAPI project resides will be AWS API Gateway. The service will retrieve data from the backends we have registered in the app. Using this generic approach we can have multiple ways to serve data as if we are working with GraphQL, where multiple data sources are behind a single endpoint. Also, we will create the mechanism (CI/CD) to deploy the code when it is pushed into the GitHub repository through AWS CodeBuild.

Project Structure

FastAPI application

FastAPI is a modern web framework for building Rest APIs which offers fast applications development, high-performance, asynchronous code executions and many other interesting and useful characteristics, and as you can figure out is the framework of election for our project today.

Routers

Supposing the application is handling CRUD operations for many resources we are creating four generic entry points and we will let you use the controller and the implemented services to specify your application logic in case of some specific scenario.

You need to specify the services (class name) you want to use to handle the requests and you need to configure a mapper where you must specify the services and the resources relation. Does it sound tricky right?

Let’s put an example: Suppose you will have a request like http://localhost:8000/api/mocks, and you want to retrieve data from a data structure implemented in memory, but for another resource like http://localhost:8000/api/users, you want to retrieve the information from the table users in DynamoDB. Let’s check the mapper needed here:

As you can see, you should have implemented the services needed to respond to the resources requested. But…, why do it in this way? Well, probably you heard before about the SOLID principles, in this specific use-case, we are using the Liskov Substitution Principle (L) and the Dependency Inversion Principle (D).

Before we go to the services, let’s create the generic service endpoints. These functions get the requests and re-direct the application flow for the controller.

Controller

Well, the function of the controller is to find the service that should respond to the requested resource and redirect the application flow to it.

At this point, the controller does not know how the services are implemented, even it does not know which services are running because is a high-level module in charge of creating those services and pass them to the controller, is here where we apply the Dependency Inversion Principle because we should depend upon abstractions, not on concrete implementations and also the Liskov Substitution Principle, this principle defines that objects of a superclass shall be replaceable with objects of its subclasses without breaking the application.

Services

The service must implement all the functions for your CRUD operations defined in the base.py abstract class. In the case where some of your services does not allow some method (for example POST, PUT, DELETE), it must raise NotImplementedError.

MockService

This is a mock service without a real backend service behind it. Probably useful for testing purposes.

DynamoService

For a more realistic service, we could use a DynamoDB table. In this case, is the same approach, we need to implement the abstract class Service, and add the service to the mapper (as we did previously).

AWS deployment

Once we have our service running and tested locally is time to deploy it into the AWS Cloud and for this purpose, we will create a SAM template.

Serverless Application Model

The Serverless Application Model (SAM) is an open-source framework created with the purpose of building serverless applications on AWS, which provides shorthand syntax to express functions, APIs, databases, and event source mappings.

AWS CodeBuild

For continuous integration and continuous deployment (CI/CD) processes, we will use AWS CodeBuild which provides full support for the Serverless Application Model.

AWS Codebuild looks for a “buildspec.yaml” in the source code root directory to run a build. This file is a collection of build commands and related settings, in YAML format.

GitHub integration

The integration between CodeBuild and GitHub is done via a webhook, that’s why we need to generate a personal access token into our GitHub account. To do that you can visit: https://github.com/settings/tokens. Below the access, you need to grant.

Secrets Manager

In the SAM template, we need to put the access we just created, but of course, putting a credential into the code is not an option. Then, because currently the use of System Manager Store Parameter service inside the SAM template is not allowed, we will use the service Secrets Manager for that purpose.

SAM template

Below, the SAM template defines the resources needed to fulfil the defined service architecture.

Deploying the infrastructure

The first deployment to AWS must be done manually using the SAM command-line interface. Later, all the deployments will be done automatically through AWS CodeBuild when the code is pushed into the repository.

Install SAM CLI

AWS provides the right tool to easily create, deploy and manage your serverless applications defined in a SAM template. You need to install and configure a few things in order to use the AWS SAM CLI.

Then, you can create the configurations and run the below commands in order to create and deploy your project infrastructure.

After the deployment is done, you must go to the Stage menu in the API Gateway console and retrieve the Invoke URL for your endpoints. Now, you are ready to send some request.

Once you upload new code to your repository, you can check the build history in AWS CodeBuild.

That’s all for today folks. Maybe, this project can be a blueprint for your next Rest API journey using a serverless architecture…

Code repository: https://github.com/alekglez/serverless-api-service

Data Architect | Python Developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store