Introduction
In modern microservices architecture, handling asynchronous workflows is a critical requirement for scalability and modularity. This blog will walk you through setting up a microservice architecture where:
- A Python Flask-based backend service handles API requests.
- AWS Step Functions orchestrate asynchronous workflows.
- AWS Lambda functions trigger the workflows and execute specific tasks.
Architecture Overview
- Flask Service: Acts as the backend entry point, invoking AWS Lambda functions to trigger workflows.
- AWS Step Functions: Manages the sequence of tasks defined in an orchestrator template.
- AWS Lambda: Acts as the intermediary, finding and triggering the appropriate AWS Step Functions state machine.
Here’s how you can set up this architecture step by step.
Step 1: Set Up Your Flask Backend Service
First, create a Python Flask application that includes a function to invoke an AWS Lambda function asynchronously.
Code Example: backend-service
from flask import Flask, request, jsonify, current_app
import boto3
import json
app = Flask(__name__)
def call_lambda(func_name, payload):
    client = boto3.client("lambda")
    client.invoke(
        FunctionName=func_name,
        InvocationType="Event",
        Payload=payload
    )
    return None
@app.route("/trigger-workflow", methods=["POST"])
def trigger_workflow():
    payload = request.get_json()
    lambda_name = f"trigger-lambda-{current_app.config['ENVIRONMENT']}"
    call_lambda(lambda_name, json.dumps(payload))
    return jsonify({"message": "Workflow triggered!"}), 200
if __name__ == "__main__":
    app.config["ENVIRONMENT"] = "dev"
    app.run(debug=True)Steps:
- Install Flask and Boto3:
pip install flask boto3
- Save the code as app.pyand run the Flask application:python app.py
- Test the endpoint by sending a POST request to /trigger-workflowwith JSON payload.
Step 2: Create the Lambda Function
The Lambda function acts as the trigger for your AWS Step Functions state machine.
Code Example: trigger-lambda.py
import os
import json
import boto3
from botocore.exceptions import ClientError
import logging
logger = logging.getLogger(__name__)
def find(stepfunctions_client, state_machine_name):
    """
    Finds a state machine by name.
    """
    state_machine_arn = None
    try:
        paginator = stepfunctions_client.get_paginator("list_state_machines")
        for page in paginator.paginate():
            for machine in page["stateMachines"]:
                if machine["name"] == state_machine_name:
                    state_machine_arn = machine["stateMachineArn"]
                    break
            if state_machine_arn:
                break
        if state_machine_arn:
            logger.info("Found state machine %s with ARN %s.", state_machine_name, state_machine_arn)
        else:
            logger.info("Couldn't find state machine %s.", state_machine_name)
    except ClientError:
        logger.exception("Couldn't find state machine %s.", state_machine_name)
        raise
    return state_machine_arn
def lambda_handler(event, context):
    sfn_client = boto3.client("stepfunctions")
    state_machine_arn = find(sfn_client, f'orchestration-{os.environ["ENVIRONMENT"]}')
    sfn_client.start_execution(
        stateMachineArn=state_machine_arn,
        input=json.dumps(event)
    )
    return {"statusCode": 200, "body": json.dumps("Step Function Triggered!")}Steps:
- Save this file as trigger-lambda.py.
- Deploy it to AWS Lambda with an IAM role that has permissions to invoke Step Functions.
- Set the environment variable ENVIRONMENTto match your setup (e.g.,dev,prod).
Step 3: Define Your Step Functions Workflow
Create a JSON template to define your Step Functions workflow.
Example: orchestrator.tmpl.json
{
  "Comment": "Workflow",
  "StartAt": "Task1",
  "States": {
    "Task1": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:Task1",
      "Next": "Task2"
    },
    "Task2": {
      "Type": "Task",
      "Resource": "arn:aws:lambda:REGION:ACCOUNT_ID:function:Task2",
      "End": true
    }
  }
}Steps:
- Replace REGIONandACCOUNT_IDwith your AWS region and account ID.
- Save the file and deploy it to AWS Step Functions.
- Name the state machine orchestration-ENVIRONMENT.
Step 4: Test the Integration
- Start the Flask server and send a POST request to /trigger-workflow:curl -X POST http://127.0.0.1:5000/trigger-workflow -H "Content-Type: application/json" -d '{"key": "value"}'
- Check the AWS Step Functions console to see the triggered workflow and its execution status.
- Review the logs in AWS CloudWatch for both the Lambda function and Step Functions.
Conclusion
Combining Flask, AWS Lambda, and Step Functions provides a powerful way to manage asynchronous workflows. This architecture is scalable, modular, and can be tailored to various use cases. Experiment with this setup and adapt it to your project requirements.




