Read the full article about Clean Architecture for Serverless here.
kotlin-clean-architecture-example-docs-flow/
│
├── build.gradle.kts // Root build file
├── settings.gradle.kts // Contains include statements for subprojects
│
├── .github/ // GitHub-specific configuration
│ └── workflows/ // GitHub Actions workflow definitions
│ ├── feature-aws.yml // Triggers AWS deployment for feature branches
│ ├── feature-azure.yml // Triggers Azure deployment for feature branches
│ ├── main-aws.yml // Triggers AWS deployment for main branch
│ ├── main-azure.yml // Triggers Azure deployment for main branch
│ ├── workflow-build-deploy-aws.yml // Reusable workflow for AWS Lambda build and deployment
│ └── workflow-build-deploy-azure.yml // Reusable workflow for Azure Function build and deployment
│
├── docs/ // Documentation files
│ └── postman/ // Postman collections and environments
│ ├── AWS Conf Demo.postman_collection.json // Collection for AWS app
│ ├── Azure Conf Demo.postman_collection.json // Collection for Azure app
│ ├── Health Checks.postman_collection.json // Collection for Initial health checks on AWS app and Azure app
│ └── Demo Example.postman_environment.json // Environment variables for both deployments
│
├── software/ // Holds all the business logic and application code
│ ├── domain/
│ │ ├── src/
│ │ └── build.gradle.kts
│ ├── application/
│ │ ├── src/
│ │ └── build.gradle.kts
│ └── infra/ // Infrastructure specific code
│ ├── aws/ // AWS-specific code, including AWS Lambda
│ │ ├── src/
│ │ └── build.gradle.kts
│ └── azure/ // Azure-specific code, including Azure Function
│ ├── src/
│ └── build.gradle.kts
│
└── cdk/ // Terraform CDK Kotlin code
├── aws/
│ ├──src/
│ ├──build.gradle.kts
│ ├──cdktf.out/ // Generated by generateTerraform.sh
│ ├──generated/ // Generated by generateTerraform.sh
│ └──generateTerraform.sh // Generates terraform json from CDK, run when infrastructure changes
└── azure/
├──src/
├──build.gradle.kts
├──cdktf.out/ // Generated by generateTerraform.sh
├──generated/ // Generated by generateTerraform.sh
└──generateTerraform.sh // Generates terraform json from CDK, run when infrastructure changes
@startuml
actor "Writer" as Writer
actor "Reviewer" as Reviewer
rectangle "Document Review System" {
(Upload Document) as Upload
(Analyze Document) as Analyze
(Send Email to Reviewer) as SendEmail
(Access Document with Token) as AccessLink
}
Writer --> Upload
Upload --> Analyze
Analyze --> SendEmail
SendEmail --> Reviewer
Reviewer --> AccessLink
@enduml- Endpoint:
/docs-flow - Method: POST
- Description: Accepts Word documents and stores them in blob storage (Azure) or S3 (AWS)
- Request Body: Word document content
- Response: JSON with document ID and URL
{ "id": "document-uuid", "url": "storage-url" }
Before you begin, ensure you have the following:
- Java 21 or later installed
- Git for version control
- Gradle (the project uses the Gradle wrapper, so you don't need to install it separately)
- IDE of your choice (IntelliJ IDEA recommended for Kotlin development)
This project can be deployed to either AWS or Azure or both. Depending on your target environment, you'll need:
- An AWS account with permissions to:
- Create and manage Lambda functions
- Create and manage API Gateway resources
- Create and manage IAM roles and policies
- Create and manage S3 buckets
- Configure SES Identities (Sandbox)
- Deploy AWS resources via Terraform
- Create identities for sender and receiver email address in your SES (Sandbox)
- An Azure account with permissions to:
- Create and manage Azure Functions
- Create and manage Storage accounts
- Create and manage Application Insights
- Create Azure Communication resources
- Assign roles to managed identities
- Deploy Azure resources via Terraform
- Register your subscription with microsoft communication:
az provider register --namespace Microsoft.Communication- wait till Registered status:
az provider show --namespace Microsoft.Communication --query "registrationState"
After checking out the project, ensure it can build properly by running:
./gradlew buildfrom the root of the project.
If you plan to deploy the infrastructure, you may need to update the following:
- Update the AWS region in the workflow file if needed (default is "eu-west-1")
- The S3 bucket for Terraform state is set to "kotlin-lambda-terraform-state" (this bucket must exist before deployment)
- The S3 bucket for Lambda deployment is set to "lambda-deployment-clean-architecture-example"
- Update the Azure resource group name (default is "DefaultResourceGroup-WEU")
- Update the Azure region if needed (default is "West Europe")
- Update the Azure data location if needed (default is "Europe")
- The storage account for DocsFlow is set to "docsflow" (this storage account must exist before deployment)
- The storage container for Terraform state is set to "cleanarchitecturesta" (this container must exist in the storage account before deployment)
Ensure to run generateTerraform.sh after any infra changes in the appropriate cdk module (aws or azure) to regenerate terraform configuration.
If you are using GitHub Actions for deployment, you'll need to configure OIDC:
Configure the following GitHub repository secrets:
AWS_ACCOUNT_ID: Your AWS account IDOIDC_ROLE_NAME: Your OIDC role name
AZURE_SUBSCRIPTION_ID: Your Azure subscription IDAZURE_OIDC_CLIENT_ID: Your Azure OIDC client IDAZURE_TENANT_ID: Your Azure tenant IDAZURE_STORAGE_ACCOUNT_NAME: Your Azure storage account nameAZURE_STORAGE_ACCOUNT_ACCESS_KEY: Your Azure storage account access key for storage account that supports the Azure Function app deployment and operation (in this example it is calledcleanarchitecturesta)
The Azure Gradle plugin (com.microsoft.azure.azurefunctions) used for deploying Azure Functions requires a storage account access key and does not support managed identity authentication yet. This is why you need to provide the AZURE_STORAGE_ACCOUNT_ACCESS_KEY as a secret in your GitHub repository for the deployment workflow to function properly.
Note that this storage account, e.g. cleanarchitecturesta, is specifically used to support the Azure Function app deployment and operation. The application also uses a separate storage account for its core functionality (document storage - docsflow).
The docs/postman directory contains Postman collections and an environment file for testing the MockNest API:
- AWS MockNest Conf Demo.postman_collection.json: Collection for testing the MockNest API deployed on AWS
- Azure MockNest Conf Demo.postman_collection.json: Collection for testing the MockNest API deployed on Azure
- Health Checks.postman_collection.json: Collection for running both AWS and Azure health checks
AWS and Azure collections contain requests for:
- Creating mock API endpoints
- Testing mock endpoints
- Resetting mappings
- Viewing near misses (requests that almost matched a mapping)
- Checking the health of the service
- Deleting mappings
Health Check collection is a shortcut to run all health checks at once.
- Demo Example.postman_environment.json: Contains environment variables used by both collections
Before using the collections, you need to configure the environment variables:
For AWS deployment:
AWS_URL: Set to your AWS API Gateway endpointapi_key: Set to your AWS API Gateway API key
For Azure deployment:
AZURE_URL: Set to your Azure Function App endpointadmin_function_key: Set to your Azure Function admin key (for admin operations)client_function_key: Set to your Azure Function mocknest key (for client operations)
If you have questions or encounter issues, please log them in the repository's issue tracker: https://github.com/elenavanengelenmaslova/kotlin-clean-architecture-example-docs-flow/issues
For further reference, please consider the following sections:
- Official Gradle documentation
- Spring Boot Gradle Plugin Reference Guide
- Create an OCI image
- Function
These additional references should also help you:
- Gradle Build Scans – insights for your project's build
- Various sample apps using Spring Cloud Function
If this project saved you time, consider buying me a coffee ☕ to help keep it up to date and maintained.




