This demo project exemplifies an Event-driven Architecture (EDA) using AWS Serverless services. The communication between the microservices is done using Amazon EventBridge with a choreographic approach.
-
Order Service is implemented using two AWS Lambda Functions
- Create Order: Receives new order from Amazon API Gateway, persist it in Amazon DynamoDB and publishes a
CreateOrder
event in Amazon EventBridge - Update Order: Triggered by any event from Payment Service, persist the new order status in Amazon DynamoDB and publish
OrderCompleted
orOrderCancelled
event in Amazon EventBridge
- Create Order: Receives new order from Amazon API Gateway, persist it in Amazon DynamoDB and publishes a
-
Payment Service implements a simple validation workflow using AWS StepFunctions
- If the order amount is less than
500
it will publish the eventPaymentSucceeded
in EventBridge, otherwisePaymentFailed
- If the order amount is less than
-
Notification Service is implemented using a Lambda function and Amazon SNS
- Triggered by all events generated by Order and Payment services, it will notify the user when they occur
Note: For sake of simplicity, the architecture uses sparse events and no data replication or query is done between the services.
- Download the sample project
git clone https://github.com/tgpadua/aws-eda-demo
- Access the created directory
cd aws-eda-demo
- Update the notification email in
lib/aws-eda-demo-stack.js
const EMAIL = '[email protected]';
- Deploy the CDK project
cdk deploy
- Check your email and click in the
Confirm subscription
link
Create a new state machine in Step Functions named eda-demo-payment-service
as in the diagram using the following state machine definition:
{
"Comment": "Payment Service",
"StartAt": "isFraud",
"States": {
"isFraud": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.detail.amount",
"NumericGreaterThan": 500,
"Next": "Payment Failed"
}
],
"Default": "Payment Succeeded"
},
"Payment Failed": {
"Type": "Pass",
"Next": "Notify EventBus",
"Result": {
"status": "PaymentFailed"
},
"ResultPath": "$.payment"
},
"Payment Succeeded": {
"Type": "Pass",
"Next": "Notify EventBus",
"Result": {
"status": "PaymentSucceeded"
},
"ResultPath": "$.payment"
},
"Notify EventBus": {
"Type": "Task",
"Resource": "arn:aws:states:::events:putEvents",
"Parameters": {
"Entries": [
{
"Detail": {
"id.$": "$.detail.id"
},
"DetailType.$": "$.payment.status",
"EventBusName": "eda-demo",
"Source": "payment-service"
}
]
},
"End": true
}
}
}
Create a bus named eda-demo
with the following rules:
Rule name: cw-catch-all
Event Pattern:
{
"source": [ { "exists": true } ]
}
Target: CloudWatch log group - eda-demo-all
Rule name: payment-service-filtering-orders
Event Pattern:
{
"source": ["order-service"],
"detail-type": ["OrderCreated"]
}
Target: Step Functions state machine - eda-demo-payment-service
Rule name: order-service-filtering-payments
{
"source": ["payment-service"]
}
Target: Lambda Function - eda-demo-update-order
Rule name: notification-service
{
"source": ["order-service","payment-service"]
}
Target: Lambda Function - eda-demo-notification
-
Set API Gateway endpoint as an environment variable
export API=<api_gateway_endpoint>
-
Create a new order
curl -X POST $API/order -d '{"id":101,"amount":100}'
-
Validate the test
- Check the Step Functions execution
- Check the DynamoDB items
- Check the CloudWatch log group targeted by
catch all
EventBridge rule - Check your emails for notifications sent by SNS
-
Repeat the steps 2 & 3 using a different
order id
andamount
over500
cdk destroy
Order Created
{
"version": "0",
"id": "0be79de6-6927-ad2d-052b-f45d95ea644c",
"detail-type": "OrderCreated",
"source": "order-service",
"account": "000000000000",
"time": "2023-05-11T01:38:00Z",
"region": "us-west-1",
"resources": [],
"detail": {
"id": 101,
"amount": 100
}
}