Serverless Python Flask API with AWS Amplify and AWS Lambda and Amazon DynamoDB
Wagner Caetano
July 8, 2023
Serverless computing is a cloud computing model where the cloud provider takes care of all the infrastructure management, so you can focus on your code. This makes it a great option for building and deploying APIs, as you don't have to worry about provisioning and managing servers.
In this article, we will show you how to create a serverless Python Flask API using AWS Amplify, AWS Lambda, and Amazon DynamoDB like I did in one of my recent college projects.
Prerequisites
- You will need an AWS account.
- You will need to install the AWS Amplify CLI.
- You will need to have Python installed.
Architecture Overview
Before diving into the implementation details, let's gain an overview of the architecture we'll be building:
- AWS Amplify: A comprehensive development platform that simplifies building serverless applications by providing frontend and backend development tools, including authentication, data storage, and APIs.
- AWS Lambda: A serverless compute service that enables running code without the need to provision or manage servers. We'll utilize Lambda functions to handle API requests and responses.
- Flask: A lightweight and flexible Python web framework that serves as the foundation for our API development.
- Amazon DynamoDB: A fully managed NoSQL database service offered by AWS. DynamoDB will store and retrieve data for our API.
Setting Up AWS Amplify
To get started with AWS Amplify, we need to install the Amplify CLI (command-line interface) on our local machine. The Amplify CLI will help us configure and deploy our backend resources on AWS. To install the Amplify CLI, run the following command in your terminal:
npm install -g @aws-amplify/cli
Next, we need to initialize an Amplify project in our working directory. To do so, run the following command:
amplify init
This will prompt you to enter some information about your project, such as the name, environment, default editor, etc. You can choose the default options or customize them as you wish. You will also need to provide your AWS credentials to allow Amplify to access your account.
Creating a REST API with AWS Lambda and Flask
Now that we have set up our Amplify project, we can create a REST API with AWS Lambda and Flask. To do so, run the following command:
amplify add api
This will prompt you to choose the type of API you want to create. Choose REST as the option and press Enter. You will then be asked to provide some information about your API, such as the name, path, authorization type, etc. For this tutorial, we will use the following values:
? Provide a friendly name for your resource to be used as a label for this category in the project: flaskapi
? Provide a path (e.g., /items) /items
? Choose a Lambda source Create a new Lambda function
? Provide a friendly name for your resource to be used as a label for this category in the project: flaskapifunction
? Provide the AWS Lambda function name: flaskapifunction
? Do you want to access other resources created in this project from your Lambda function? No
? Do you want to invoke this function on a recurring schedule? No
? Do you want to configure Lambda layers for this function? No
? Do you want to edit the local lambda function now? Yes
? Restrict API access No
? Do you want to add another path? No
This will create a new folder called amplify/backend/api/flaskapi with some files and folders inside it. The most important file is the lambda/index.js file, which contains the code for our Lambda function.
Amplify uses venv to build the function so you can specify which packages you might want to use on this file "Pipfile"
function folder
Pipfile
In my case I was using this packages, to setup a aws-wsgi handler inside the function, boto3 to use AWS services and flask for the Api. Also remember to edit the cloudformation-template.json file, since you might need to change python version and add more permissions to your function.
After configuring everything you can edit the function and add a code like this:
import boto
import awsgi
import os
from flask_cors import CORS
from flask import Flask, jsonify
client = boto3.client('dynamodb')
BASE_ROUTE = "/clients"
TABLE_NAME = os.environ.get('TABLE_NAME_CLIENTS')
app = Flask(__name__)
CORS(app)
@app.route(BASE_ROUTE + '/<id>', methods=['GET'])
def getInfo(id):
account = client.get_item(TableName=TABLE_NAME, Key={
'id': {'S': id}})
return jsonify(data=account)
def handler(event, context):
return awsgi.response(app, event, context)
Here we are setting up boto3 client to get itens filtered from dynamo db table (you can have one previously created or you can continue to tutorial to create one later). As well as defining the handler to be awsgi that will pass the request along for your "getInfo" method.
Add DynamoDB as a data source for the API
Next, we will add DynamoDB as a data source for our API. DynamoDB is a fast and flexible NoSQL database service that can store and retrieve any amount of data with low latency and high availability.
To add DynamoDB as a data source for our API, we will use Amplify CLI's storage category. The storage category allows us to create and manage data sources for our serverless applications. To add a storage category to our project, run the following command in your terminal:
amplify add storage
This will ask you some questions about your data source, such as the name, type, schema, etc. You can choose the default options or customize them as you like. For example, I chose the following options:
? Please select from one of the below mentioned services: NoSQL Databas
? Provide a friendly name for your resource that will be used to label this category in
the project: flaskapidb
? Please provide table name: Item
? What would you like to name this column: id
? Please choose the data type: string
? Would you like to add another column? Yes
? What would you like to name this column: name
? Please choose the data type: string
? Would you like to add another column? Yes
? What would you like to name this column: price
? Please choose the data type: number
? Would you like to add another column? No
? Please choose partition key for the table: id
? Do you want to add a sort key to your table? No
? Do you want to add global secondary indexes to your table? No
? Do you want to add a Lambda Trigger for your Table? Noe
After answering these questions, Amplify CLI will create a new directory called amplify/backend/storage/flaskapidb
and add a DynamoDB table called Item
with three columns: id
, name
, and price
. It will also update the amplify/backend/backend-config.json
file with the storage configuration.
Test the API locally and deploy it to the cloud
Finally, we can test our API locally and deploy it to the cloud. To test our API locally, we need to install Amplify CLI's mock feature. The mock feature allows us to run our serverless applications locally without connecting to any cloud resources. To install the mock feature, run the following command in your terminal:
amplify mock api
This will start a local server that simulates our REST endpoint and Lambda function. It will also create a local instance of DynamoDB that mimics our cloud table. We can access our local API at http://localhost:3000/items.
To deploy our API to the cloud, we need to push our changes to Amplify CLI. The push command will create or update all the backend resources in the cloud according to our local configuration. To push you can run the following command:
amplify push -y
(Obs: be aware that you are going to need venv and some other packages to publish you function, so if you get an error, it might be because of missing python packages.)