{
"Comment": "Express usage query: low-latency EXPRESS workflow for real-time energy usage checks. Validates the meter, calculates current usage immediately, and screens for anomalies before returning live data with a short telemetry sync Wait.",
"StartAt": "SetQueryMeta",
"States": {
"SetQueryMeta": {
"Type": "Pass",
"Parameters": {
"meterId.$": "$.meterId",
"accountId.$": "$.accountId",
"currentReading.$": "$.currentReading",
"previousReading.$": "$.previousReading",
"readingDate.$": "$.readingDate",
"unit.$": "$.unit",
"workflow": "EXPRESS_USAGE_QUERY",
"expedited": true
},
"Next": "ValidateMeterReading"
},
"ValidateMeterReading": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "${ValidateMeterReadingFunctionArn}",
"Payload.$": "$"
},
"ResultPath": "$.validation",
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException"
],
"IntervalSeconds": 1,
"MaxAttempts": 2,
"BackoffRate": 2
}
],
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.error",
"Next": "InvalidMeterData"
}
],
"Next": "IsReadingValid"
},
"IsReadingValid": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.validation.Payload.isValid",
"BooleanEquals": true,
"Next": "CalculateUsage"
}
],
"Default": "InvalidMeterData"
},
"CalculateUsage": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "${CalculateUsageFunctionArn}",
"Payload.$": "$"
},
"ResultPath": "$.usage",
"Retry": [
{
"ErrorEquals": [
"States.ALL"
],
"IntervalSeconds": 1,
"MaxAttempts": 2,
"BackoffRate": 2
}
],
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.error",
"Next": "UsageQueryError"
}
],
"Next": "AnomalyScreen"
},
"AnomalyScreen": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"FunctionName": "${DetectAnomalyFunctionArn}",
"Payload.$": "$"
},
"ResultPath": "$.anomaly",
"Retry": [
{
"ErrorEquals": [
"States.ALL"
],
"IntervalSeconds": 1,
"MaxAttempts": 2,
"BackoffRate": 2
}
],
"Catch": [
{
"ErrorEquals": [
"States.ALL"
],
"ResultPath": "$.error",
"Next": "UsageQueryError"
}
],
"Next": "IsAnomalyDetected"
},
"IsAnomalyDetected": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.anomaly.Payload.isAnomaly",
"BooleanEquals": false,
"Next": "TelemetrySyncWait"
}
],
"Default": "AnomalyFlagged"
},
"TelemetrySyncWait": {
"Type": "Wait",
"Comment": "Short wait for telemetry data to propagate to the usage dashboard.",
"Seconds": 2,
"Next": "UsageDataLive"
},
"UsageDataLive": {
"Type": "Succeed"
},
"AnomalyFlagged": {
"Type": "Fail",
"Error": "AnomalyDetected",
"Cause": "Anomalous usage detected — query result held for review"
},
"InvalidMeterData": {
"Type": "Fail",
"Error": "InvalidMeterData",
"Cause": "Meter reading failed validation — cannot process usage query"
},
"UsageQueryError": {
"Type": "Fail",
"Error": "UsageQueryError",
"Cause": "Usage calculation or anomaly detection lambda encountered an unexpected error"
}
}
}JSONExpand
100%
Energy teams can use patterns like this to build reliable, compliant, and scalable automation for payment systems and can test and refine these flows locally with Thrubit to reduce cloud cost and speed up iteration.