This is part 2 of my last post, “Building a Serverless Event-Driven Order Fulfillment System using AWS Event Bridge“. In Part 1, I’ve already setup the infrastructure to accept orders and publish them as events to EventBridge, along with routing them to an API destination and CloudWatch log group. For the next steps, we can build upon that foundation and add two more rules to further process the orders.
Step 4: Route Orders to Workflow
Here is a very simple workflow that listens to new order events from the EventBridge and publishes back an order processed event. In a more complicated case we can pass the content of the event from EventBridge and use the event payload in the Step Functions.
To create a workflow, go to Step Functions console and create a New State Machine.
With the Visual Designer, select Flow and drag a Pass state to the workflow:
Next we select Actions and choose Amazon EventBridge and add a PutEvents.
To write an event with a “Order Processed” type to your Orders event bus via the PutEvents API Parameters, you’ll need to provide the following JSON payload.
{
"Entries": [
{
"Detail": {
"OrderId": "new_id",
"OrderDetails.$": "$.detail"
},
"DetailType": "Order Processed",
"EventBusName": "Orders",
"Source": "com.aws.orders"
}
]
}
Additionally, make sure to unselect the “Wait for callback” option if it’s selected, as you don’t need to wait for a callback in this scenario.
Now we can define a new event rule ‘EUOrdertoStepFunctions‘ specifically targeting orders with ‘EU’ locations to the workflow in Step Functions.
For event pattern, match orders with locations originating from ‘eu-west‘ only.
Choose Step Functions state machine as the target and workflow created earlier in State machine:
To trigger the execution of our workflow, let’s make a call to our Producer API with the following parameters:
https://xxx.execute-api.ca-central-1.amazonaws.com/dev?location=eu-west&category=office-supplies&value=300
Once the request is made successfully, our Producer API will publish the order event to EventBridge, triggering the associated event rule, which in turn will invoke the Step Functions workflow to process the order.
Step 5: Route Orders to Lambda Function and DynamoDB
To complete the order processing flow, we will create a new event rule that routes processed order events to a Lambda function. This Lambda function will store the order details in a DynamoDB table and then publish a dispatch order event to the Orders event bus.
An order consists of an orderId with the following attributes:
- category
- location
- value
First, create a new DynamoDB table with the following details:
- Table name: OrderDetails
- Partition key: orderId
- Partition key type: String
To allow the Lambda function to write to the DynamoDB table, I need to create an IAM policy with the appropriate permissions as follow and attach it to the Lambda function’s execution role.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Allow",
"Action": [
"dynamodb:BatchGetItem",
"dynamodb:GetItem",
"dynamodb:Query",
"dynamodb:Scan",
"dynamodb:BatchWriteItem",
"dynamodb:PutItem",
"dynamodb:UpdateItem",
"events:PutEvents"
],
"Resource": [
"arn:aws:dynamodb:*:*:table/OrderDetails",
"arn:aws:events:*:*:event-bus/Orders"
]
}
]
}
The policy also grants the Lambda function to write events to our Orders event bus. Now let’s create a Lambda function that performs the following:
- Read order details (category, location, value) from the order event payload
- Generate a new order id and save the order details to the OrderDetails table
- Publish a order dispatch event with order details to Orders event bus
Edit the Lambda function’s execution role and attach our new IAM policy to it. Verify the function has permissions to access both the DynamoDB and EventBridge.
To create an EventBridge rule that routes only processed orders to my Lambda function, define an event pattern that matches events with the “Order Processed” detail type.
{
"source": ["com.aws.orders"],
"detail-type": ["Order Processed"]
}
Choose the Lambda function created as target and save the rule.
Test our Lambda function logic by calling our Producer API with the following parameters.
https://xxx.execute-api.ca-central-1.amazonaws.com/dev?location=eu-west&category=general-supplies&value=300
Verify that the order details are successfully saved into the DynamoDB OrderDetails table.
A dispatch order event with the same orderId is published to the Orders event bus, indicating that our Lambda function has successfully executed its logic.
Summary
My serverless event-driven order fulfillment system is now fully operational, handling the end-to-end process of order submission, processing, and dispatching. I hope you can see how quickly it is to add extensions to a system that builds on Event-Driven Architecture. This approach allows for new functionalities without the need to change the event publisher-consumer model.
You can find all the source codes in my GitHub repository. Thank you for reading my post.