Structure a Python project in hexagonal architecture using AWS Lambda
Created by Furkan Oruc (AWS), Dominik Goby (AWS), Darius Kunce (AWS), and Michal Ploski (AWS)
Environment: PoC or pilot | Technologies: DevelopmentAndTesting; CloudNative; Containers & microservices; Serverless; Modernization | AWS services: Amazon DynamoDB; AWS Lambda; Amazon API Gateway |
Summary
This pattern shows how to structure a Python project in hexagonal architecture by using AWS Lambda. The pattern uses the AWS Cloud Development Kit (AWS CDK) as the infrastructure as code (IaC) tool, Amazon API Gateway as the REST API, and Amazon DynamoDB as the persistence layer. Hexagonal architecture follows domain-driven design principles. In hexagonal architecture, software consists of three components: domain, ports, and adapters. For detailed information about hexagonal architectures and their benefits, see the guide Building hexagonal architectures on AWS.
Prerequisites and limitations
Prerequisites
An active AWS account
Experience in Python
Familiarity with AWS Lambda, AWS CDK, Amazon API Gateway, and DynamoDB
A GitHub account (see instructions for signing up
) Git (see installation instructions
) A code editor for making changes and pushing your code to GitHub (for example, AWS Cloud9,
Visual Studio Code , or JetBrains PyCharm ) Docker installed, and the Docker daemon up and running
Product versions
Git version 2.24.3 or later
Python version 3.7 or later
AWS CDK v2
Poetry version 1.1.13 or later
AWS Lambda Powertools for Python version 1.25.6 or later
pytest version 7.1.1 or later
Moto version 3.1.9 or later
pydantic version 1.9.0 or later
Boto3 version 1.22.4 or later
mypy-boto3-dynamodb version 1.24.0 or later
Architecture
Target technology stack
The target technology stack consists of a Python service that uses API Gateway, Lambda, and DynamoDB. The service uses a DynamoDB adapter to persist data. It provides a function that uses Lambda as the entry point. The service uses Amazon API Gateway to expose a REST API. The API uses AWS Identity and Access Management (IAM) for the authentication of clients.
Target architecture
To illustrate the implementation, this pattern deploys a serverless target architecture. Clients can send requests to an API Gateway endpoint. API Gateway forwards the request to the target Lambda function that implements the hexagonal architecture pattern. The Lambda function performs create, read, update, and delete (CRUD) operations on a DynamoDB table.
Important: This pattern was tested in a PoC environment. You must conduct a security review to identify the threat model and create a secure code base before you deploy any architecture to a production environment. |
---|
The API supports five operations on a product entity:
GET /products
returns all products.POST /products
creates a new product.GET /products/{id}
returns a specific product.PUT /products/{id}
updates a specific product.DELETE /products/{id}
deletes a specific product.
You can use the following folder structure to organize your project to follow the hexagonal architecture pattern:
app/ # application code |--- adapters/ # implementation of the ports defined in the domain |--- tests/ # adapter unit tests |--- entrypoints/ # primary adapters, entry points |--- api/ # api entry point |--- model/ # api model |--- tests/ # end to end api tests |--- domain/ # domain to implement business logic using hexagonal architecture |--- command_handlers/ # handlers used to execute commands on the domain |--- commands/ # commands on the domain |--- events/ # events triggered via the domain |--- exceptions/ # exceptions defined on the domain |--- model/ # domain model |--- ports/ # abstractions used for external communication |--- tests/ # domain tests |--- libraries/ # List of 3rd party libraries used by the Lambda function infra/ # infrastructure code simple-crud-app.py # AWS CDK v2 app
Tools
AWS services
Amazon API Gateway
is a fully managed service that makes it easy for developers to create, publish, maintain, monitor, and secure APIs at any scale. Amazon DynamoDB
is a fully managed, serverless, key-value NoSQL database that is designed to run high-performance applications at any scale. AWS Lambda
is a serverless, event-driven compute service that lets you run code for virtually any type of application or backend service without provisioning or managing servers. You can launch Lambda functions from over 200 AWS services and software as a service (SaaS) applications, and only pay for what you use.
Tools
Git
is used as the version control system for code development in this pattern. Python
is used as the programming language for this pattern. Python provides high-level data structures and an approach to object-oriented programming. AWS Lambda provides a built-in Python runtime that simplifies the operation of Python services. Visual Studio Code
is used as the IDE for development and testing for this pattern. You can use any IDE that supports Python development (for example, AWS Cloud9 or PyCharm ). AWS Cloud Development Kit (AWS CDK
) is an open-source software development framework that lets you define your cloud application resources by using familiar programming languages. This pattern uses the CDK to write and deploy cloud infrastructure as code. Poetry
is used to manage dependencies in the pattern. Docker
is used by the AWS CDK to build the Lambda package and layer.
Code
The code for this pattern is available in the GitHub Lambda hexagonal architecture sample
Best practices
To use this pattern in a production environment, follow these best practices:
Use customer managed keys in AWS Key Management Service (AWS KMS) to encrypt Amazon CloudWatch log groups and Amazon DynamoDB tables.
Configure AWS WAF for Amazon API Gateway to allow access only from your organization's network.
Consider other options for API Gateway authorization if IAM doesn’t meet your needs. For example, you can use Amazon Cognito user pools or API Gateway Lambda authorizers.
Use DynamoDB backups.
Configure Lambda functions with a virtual private cloud (VPC) deployment to keep network traffic inside the cloud.
Update the allowed origin configuration for cross-origin resource sharing (CORS) preflight
to restrict access to the requesting origin domain only. Use cdk-nag to check the AWS CDK code for security best practices.
Consider using code scanning tools to find common security issues in the code. For example, Bandit
is a tool that’s designed to find common security issues in Python code. Pip-audit scans Python environments for packages that have known vulnerabilities.
This pattern uses AWS X-Ray
Epics
Task | Description | Skills required |
---|---|---|
Create your own repository. |
| App developer |
Install dependencies. |
| App developer |
Configure your IDE. | We recommend Visual Studio Code, but you can use any IDE of your choice that supports Python. The following steps are for Visual Studio Code.
| App developer |
Run unit tests, option 1: Use Visual Studio Code. |
| App developer |
Run unit tests, option 2: Use shell commands. |
| App developer |
Task | Description | Skills required |
---|---|---|
Request temporary credentials. | To have AWS credentials on the shell when you run | App developer, AWS DevOps |
Deploy the application. |
| App developer, AWS DevOps |
Test the API, option 1: Use the console. | Use the API Gateway console to test the API. For more information about API operations and request/response messages, see the API usage section of the readme file | App developer, AWS DevOps |
Test the API, option 2: Use Postman. | If you want to use a tool such as Postman
| App developer, AWS DevOps |
Task | Description | Skills required |
---|---|---|
Write unit tests for the business domain. |
| App developer |
Implement commands and command handlers. |
| App developer |
Write integration tests for secondary adapters. |
| App developer |
Implement secondary adapters. |
| App developer |
Write end-to-end tests. |
| App developer |
Implement primary adapters. |
| App developer |
Related resources
APG guide
AWS References
Tools
IDEs