AWS Step Functions: Điều Phối Workflow Serverless Cho Hệ Thống Phân Tán
Posted on: 4/25/2026 12:16:25 PM
Table of contents
- 1. Vì sao cần một "nhạc trưởng" cho kiến trúc serverless?
- 2. Amazon States Language — ngôn ngữ mô tả workflow
- 3. Kiến trúc tổng quan: Step Functions trong hệ thống event-driven
- 4. Standard vs Express Workflow — chọn đúng loại cho đúng bài toán
- 5. Error Handling — chiến lược chống lỗi ba lớp
- 6. Distributed Map — xử lý song song hàng triệu items
- 7. Callback Pattern — chờ đợi hành động bên ngoài
- 8. Tích hợp với Bedrock — AI workflow trong Step Functions
- 9. Redrive — khôi phục workflow thất bại mà không chạy lại từ đầu
- 10. Best practices cho production
- 11. So sánh Step Functions với các giải pháp khác
- 12. Kết luận
1. Vì sao cần một "nhạc trưởng" cho kiến trúc serverless?
Khi hệ thống chỉ có một Lambda function xử lý một nhiệm vụ đơn lẻ, mọi thứ rất đơn giản. Nhưng khi bạn cần xử lý đơn hàng — validate input, kiểm tra tồn kho, charge thanh toán, gửi email xác nhận, cập nhật inventory — năm bước đó phải chạy đúng thứ tự, xử lý lỗi từng bước, và có khả năng retry khi bất kỳ bước nào thất bại. Viết logic điều phối này trực tiếp trong code Lambda dẫn đến một hàm "god function" hàng nghìn dòng, trộn lẫn business logic với error handling, retry, và state management.
AWS Step Functions giải quyết vấn đề này bằng cách tách logic điều phối ra khỏi logic xử lý. Mỗi bước xử lý (Lambda, API call, DynamoDB operation) vẫn là đơn vị độc lập, còn Step Functions đóng vai trò nhạc trưởng — quyết định bước nào chạy tiếp, xử lý lỗi ra sao, và khi nào cần chờ đợi.
2. Amazon States Language — ngôn ngữ mô tả workflow
Step Functions sử dụng Amazon States Language (ASL) — một đặc tả JSON để mô tả state machine. Mỗi workflow là một tập hợp các state (trạng thái), mỗi state thực hiện một hành động cụ thể và chỉ định state tiếp theo. ASL hỗ trợ 8 kiểu state, mỗi kiểu phục vụ một mục đích khác nhau trong luồng xử lý.
| State Type | Mục đích | Use case điển hình |
|---|---|---|
Task | Thực thi một đơn vị công việc (Lambda, API call, SDK integration) | Gọi Lambda xử lý ảnh, gọi DynamoDB PutItem |
Choice | Rẽ nhánh dựa trên điều kiện | Kiểm tra số tiền > $100 thì cần approval |
Parallel | Chạy song song nhiều nhánh, chờ tất cả hoàn thành | Xử lý ảnh: resize + watermark + metadata cùng lúc |
Map | Lặp qua mảng items, xử lý từng item | Xử lý từng dòng trong file CSV |
Wait | Tạm dừng trong khoảng thời gian nhất định | Chờ 24h trước khi gửi email nhắc nhở |
Pass | Chuyển tiếp input sang output, có thể transform data | Chèn giá trị mặc định, reshape JSON |
Succeed / Fail | Kết thúc workflow thành công hoặc thất bại | Báo lỗi kèm error code và message |
Một ví dụ ASL đơn giản cho luồng xử lý đơn hàng:
{
"Comment": "Order Processing Workflow",
"StartAt": "ValidateOrder",
"States": {
"ValidateOrder": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-southeast-1:123456:function:validate-order",
"Next": "CheckInventory",
"Retry": [
{
"ErrorEquals": ["ServiceException"],
"IntervalSeconds": 2,
"MaxAttempts": 3,
"BackoffRate": 2.0
}
],
"Catch": [
{
"ErrorEquals": ["ValidationError"],
"Next": "OrderRejected"
}
]
},
"CheckInventory": {
"Type": "Task",
"Resource": "arn:aws:states:::dynamodb:getItem",
"Parameters": {
"TableName": "Inventory",
"Key": { "ProductId": { "S.$": "$.productId" } }
},
"Next": "IsInStock"
},
"IsInStock": {
"Type": "Choice",
"Choices": [
{
"Variable": "$.Item.Quantity.N",
"NumericGreaterThan": 0,
"Next": "ProcessPayment"
}
],
"Default": "OutOfStock"
},
"ProcessPayment": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-southeast-1:123456:function:process-payment",
"Next": "FulfillOrder"
},
"FulfillOrder": {
"Type": "Parallel",
"Branches": [
{
"StartAt": "UpdateInventory",
"States": {
"UpdateInventory": {
"Type": "Task",
"Resource": "arn:aws:states:::dynamodb:updateItem",
"Parameters": {
"TableName": "Inventory",
"Key": { "ProductId": { "S.$": "$.productId" } },
"UpdateExpression": "SET Quantity = Quantity - :qty",
"ExpressionAttributeValues": { ":qty": { "N.$": "$.quantity" } }
},
"End": true
}
}
},
{
"StartAt": "SendConfirmation",
"States": {
"SendConfirmation": {
"Type": "Task",
"Resource": "arn:aws:states:::ses:sendEmail",
"Parameters": {
"Destination": { "ToAddresses.$": "States.Array($.email)" },
"Message": {
"Subject": { "Data": "Order Confirmed" },
"Body": { "Text": { "Data.$": "$.confirmationMessage" } }
}
},
"End": true
}
}
}
],
"Next": "OrderCompleted"
},
"OrderCompleted": { "Type": "Succeed" },
"OrderRejected": { "Type": "Fail", "Error": "OrderRejected", "Cause": "Order validation failed" },
"OutOfStock": { "Type": "Fail", "Error": "OutOfStock", "Cause": "Product is out of stock" }
}
}
Không cần viết Lambda cho mọi thứ
Từ 2023, Step Functions hỗ trợ SDK Integration — gọi trực tiếp hơn 220 dịch vụ AWS mà không cần viết Lambda trung gian. Ví dụ: đọc/ghi DynamoDB, gửi SQS message, publish SNS notification, gọi ECS RunTask, thậm chí invoke Bedrock model — tất cả chỉ bằng ASL. Điều này giảm đáng kể số lượng Lambda function cần maintain, giảm latency (bỏ cold start), và giảm chi phí.
3. Kiến trúc tổng quan: Step Functions trong hệ thống event-driven
Step Functions không hoạt động đơn lẻ — nó là trung tâm điều phối trong một hệ sinh thái serverless rộng hơn. Sơ đồ dưới đây minh họa cách Step Functions kết nối các thành phần trong một kiến trúc production điển hình.
flowchart TB
subgraph TRIGGER["Trigger Sources"]
API["API Gateway"]
EB["EventBridge Rule"]
SQS["SQS Queue"]
S3E["S3 Event"]
SCH["EventBridge Scheduler"]
end
subgraph SFN["AWS Step Functions"]
SM["State Machine"]
SM --> T1["Task: Validate"]
T1 --> C1{"Choice: Route"}
C1 -->|"Path A"| T2["Task: Process"]
C1 -->|"Path B"| T3["Task: Reject"]
T2 --> P1["Parallel: Fulfill"]
P1 --> T4["Task: Notify"]
end
subgraph SERVICES["AWS Services"]
LAM["Lambda Functions"]
DDB["DynamoDB"]
SNS["SNS Topics"]
SES["SES Email"]
BDR["Bedrock AI"]
end
subgraph OBS["Observability"]
CW["CloudWatch Logs"]
XR["X-Ray Tracing"]
MET["CloudWatch Metrics"]
end
API --> SM
EB --> SM
SQS --> SM
S3E --> SM
SCH --> SM
SM --> LAM
SM --> DDB
SM --> SNS
SM --> SES
SM --> BDR
SM --> CW
SM --> XR
SM --> MET
Hình 1: Step Functions là trung tâm điều phối, kết nối trigger sources, AWS services và observability stack
4. Standard vs Express Workflow — chọn đúng loại cho đúng bài toán
Đây là quyết định quan trọng nhất khi thiết kế workflow vì không thể thay đổi loại sau khi đã tạo state machine. Hai loại workflow phục vụ hai phân khúc bài toán hoàn toàn khác nhau về throughput, durability, và chi phí.
| Tiêu chí | Standard Workflow | Express Workflow |
|---|---|---|
| Thời gian chạy tối đa | 1 năm | 5 phút |
| Execution semantics | Exactly-once | At-least-once (async) / At-most-once (sync) |
| State transition rate | Throttled theo quota | Không giới hạn |
| Pricing | Tính theo state transition ($0.025/1,000) | Tính theo số execution + duration + memory |
| Execution history | Lưu 90 ngày, truy vấn qua API | Chỉ qua CloudWatch Logs |
| Distributed Map | Có | Không |
| Wait for Callback | Có (.waitForTaskToken) | Không |
| Activities | Có | Không |
Khi nào chọn Express?
Express Workflow sinh ra cho các bài toán high-volume, short-duration, idempotent: xử lý IoT event stream (hàng triệu message/giây), transform data real-time từ Kinesis, backend cho mobile app cần response nhanh. Nếu business logic của bạn yêu cầu exactly-once semantics (ví dụ: charge thanh toán), bắt buộc phải dùng Standard — hoặc tự implement idempotency trong Lambda.
4.1. Phân tích chi phí thực tế
Giả sử bạn có một workflow xử lý đơn hàng với 8 state transitions, chạy 100,000 lần/tháng:
Con số 11× chênh lệch không có nghĩa Express luôn rẻ hơn. Nếu workflow chạy lâu (>30 giây) với memory cao, Express có thể đắt hơn Standard. Quy tắc đơn giản: workflow ngắn, nhiều lần → Express; workflow dài, ít lần → Standard.
5. Error Handling — chiến lược chống lỗi ba lớp
Xử lý lỗi trong hệ thống phân tán là bài toán phức tạp nhất. Step Functions cung cấp ba cơ chế xử lý lỗi, mỗi cơ chế phục vụ một tầng khác nhau của chiến lược resilience.
flowchart TD
A["Task Execution"] --> B{"Thành công?"}
B -->|"Có"| C["Next State"]
B -->|"Không"| D{"Retry Policy?"}
D -->|"Có & còn attempts"| E["Exponential Backoff"]
E --> A
D -->|"Hết attempts"| F{"Catch Block?"}
F -->|"Có"| G["Fallback State"]
F -->|"Không"| H["Workflow Failed"]
G --> I{"Recovery
thành công?"}
I -->|"Có"| C
I -->|"Không"| H
style A fill:#f8f9fa,stroke:#e94560,color:#2c3e50
style C fill:#4CAF50,stroke:#fff,color:#fff
style H fill:#e94560,stroke:#fff,color:#fff
style E fill:#ff9800,stroke:#fff,color:#fff
style G fill:#2196F3,stroke:#fff,color:#fff
Hình 2: Ba lớp xử lý lỗi — Retry → Catch → Workflow Fail
5.1. Retry với Exponential Backoff
Retry là tuyến phòng thủ đầu tiên — phù hợp cho lỗi tạm thời (transient errors) như network timeout, throttling, hoặc service temporarily unavailable.
"Retry": [
{
"ErrorEquals": ["States.TaskFailed"],
"IntervalSeconds": 2,
"MaxAttempts": 3,
"BackoffRate": 2.0,
"MaxDelaySeconds": 60,
"JitterStrategy": "FULL"
},
{
"ErrorEquals": ["States.Timeout"],
"IntervalSeconds": 5,
"MaxAttempts": 2,
"BackoffRate": 3.0
}
]
JitterStrategy: "FULL" là tính năng quan trọng — nó thêm random delay vào mỗi lần retry để tránh thundering herd khi nhiều workflow cùng retry đồng thời vào một service đang quá tải. Không có jitter, 1,000 workflow fail cùng lúc sẽ retry cùng lúc, tạo thêm một đợt spike.
5.2. Catch và Fallback States
Khi retry hết số lần cho phép, Catch block chuyển workflow sang một fallback state — nơi bạn implement logic compensation hoặc graceful degradation.
"Catch": [
{
"ErrorEquals": ["PaymentDeclined"],
"ResultPath": "$.error",
"Next": "NotifyPaymentFailed"
},
{
"ErrorEquals": ["States.ALL"],
"ResultPath": "$.error",
"Next": "GeneralErrorHandler"
}
]
Mẹo production: ResultPath giữ nguyên context
Luôn set ResultPath trong Catch block (ví dụ "$.error") thay vì để mặc định. Mặc định, error output sẽ ghi đè toàn bộ state input, khiến fallback state mất hết context ban đầu (orderId, userId...). Với "$.error", error info được gắn vào field riêng trong input gốc — fallback state có cả dữ liệu gốc lẫn thông tin lỗi.
6. Distributed Map — xử lý song song hàng triệu items
Distributed Map là tính năng mạnh nhất của Step Functions cho bài toán batch processing. Khác với Inline Map (xử lý tuần tự hoặc song song giới hạn 40 items/lần trong cùng một execution), Distributed Map phân tách workload thành hàng nghìn child executions chạy độc lập.
flowchart LR
S3["S3 Bucket
10M files"] --> DM["Distributed Map
State"]
DM --> B1["Batch 1
Child Workflow"]
DM --> B2["Batch 2
Child Workflow"]
DM --> B3["Batch 3
Child Workflow"]
DM --> BN["...
Batch N"]
B1 --> R["Result
Aggregation"]
B2 --> R
B3 --> R
BN --> R
R --> NX["Next State"]
style DM fill:#e94560,stroke:#fff,color:#fff
style R fill:#4CAF50,stroke:#fff,color:#fff
Hình 3: Distributed Map phân tách workload từ S3 thành hàng nghìn child workflow song song
{
"Type": "Map",
"ItemProcessor": {
"ProcessorConfig": {
"Mode": "DISTRIBUTED",
"ExecutionType": "EXPRESS"
},
"StartAt": "ProcessImage",
"States": {
"ProcessImage": {
"Type": "Task",
"Resource": "arn:aws:lambda:ap-southeast-1:123456:function:resize-image",
"End": true
}
}
},
"ItemReader": {
"Resource": "arn:aws:states:::s3:listObjectsV2",
"Parameters": {
"Bucket": "my-image-bucket",
"Prefix": "uploads/2026-04/"
}
},
"MaxConcurrency": 1000,
"ToleratedFailurePercentage": 5,
"Label": "ImageProcessing"
}
Các tham số quan trọng:
MaxConcurrency: Giới hạn số child execution chạy đồng thời. Đặt quá cao sẽ throttle downstream service (ví dụ DynamoDB write capacity). Bắt đầu từ 100, tăng dần theo khả năng chịu tải của target.ToleratedFailurePercentage: Cho phép một tỷ lệ nhất định child execution thất bại mà workflow cha vẫn thành công. Với 10 triệu items, 5% tolerance nghĩa là 500,000 items được phép fail — hữu ích cho batch job mà individual failure không critical.ExecutionType: EXPRESS: Child workflow chạy ở Express mode để tối ưu chi phí và throughput. Mỗi child phải hoàn thành trong 5 phút.
Case study: Capital One xử lý nhanh hơn 80%
Capital One sử dụng Distributed Map để xử lý hàng triệu giao dịch tài chính hàng đêm. Trước đó, pipeline chạy trên EC2 fleet mất 8 tiếng. Sau khi chuyển sang Step Functions Distributed Map, thời gian xử lý giảm xuống còn 1.5 tiếng — nhanh hơn 80% và loại bỏ hoàn toàn overhead quản lý infrastructure.
7. Callback Pattern — chờ đợi hành động bên ngoài
Không phải mọi bước trong workflow đều hoàn thành ngay. Có những bước cần chờ con người approve, chờ hệ thống bên thứ ba callback, hoặc chờ một process chạy hàng giờ hoàn thành. Step Functions giải quyết bài toán này bằng .waitForTaskToken.
{
"WaitForApproval": {
"Type": "Task",
"Resource": "arn:aws:states:::sqs:sendMessage.waitForTaskToken",
"Parameters": {
"QueueUrl": "https://sqs.ap-southeast-1.amazonaws.com/123456/approval-queue",
"MessageBody": {
"taskToken.$": "$$.Task.Token",
"orderId.$": "$.orderId",
"amount.$": "$.amount",
"approvalUrl.$": "States.Format('https://internal.example.com/approve?token={}', $$.Task.Token)"
}
},
"TimeoutSeconds": 86400,
"Next": "ExecuteOrder"
}
}
Luồng hoạt động: Step Functions gửi message chứa taskToken vào SQS → ứng dụng approval đọc message, hiển thị UI cho manager → manager approve → ứng dụng gọi SendTaskSuccess(taskToken, output) → Step Functions tiếp tục workflow. Nếu không ai approve trong 24h (TimeoutSeconds: 86400), workflow tự động chuyển sang timeout error.
8. Tích hợp với Bedrock — AI workflow trong Step Functions
Từ tháng 3/2026, Step Functions bổ sung tích hợp trực tiếp với Amazon Bedrock và Bedrock AgentCore. Điều này cho phép xây dựng AI pipeline hoàn toàn serverless — không cần Lambda wrapper.
{
"AnalyzeSentiment": {
"Type": "Task",
"Resource": "arn:aws:states:::bedrock:invokeModel",
"Parameters": {
"ModelId": "anthropic.claude-sonnet-4-6-20250514",
"ContentType": "application/json",
"Body": {
"anthropic_version": "bedrock-2023-05-31",
"max_tokens": 500,
"messages": [
{
"role": "user",
"content.$": "States.Format('Analyze the sentiment of this customer review and respond with JSON containing sentiment (positive/negative/neutral) and confidence score: {}', $.reviewText)"
}
]
}
},
"ResultSelector": {
"analysis.$": "$.Body.content[0].text"
},
"Next": "RouteBySentiment"
}
}
Pattern này đặc biệt mạnh khi kết hợp với Distributed Map: bạn có thể phân tích sentiment hàng triệu review khách hàng song song, mỗi review gọi Bedrock model trực tiếp từ ASL mà không viết dòng code nào.
9. Redrive — khôi phục workflow thất bại mà không chạy lại từ đầu
Trước Redrive, khi một workflow dài 15 bước thất bại ở bước thứ 12, bạn phải chạy lại từ bước 1 — lãng phí thời gian và chi phí cho 11 bước đã thành công. Redrive cho phép restart từ đúng điểm thất bại.
flowchart LR
S1["Step 1 ✓"] --> S2["Step 2 ✓"] --> S3["Step 3 ✓"]
S3 --> S4["Step 4 ✗
Failed"]
S4 -.->|"Redrive"| S4R["Step 4
Retry"]
S4R --> S5["Step 5"] --> S6["Step 6 ✓
Complete"]
style S1 fill:#4CAF50,stroke:#fff,color:#fff
style S2 fill:#4CAF50,stroke:#fff,color:#fff
style S3 fill:#4CAF50,stroke:#fff,color:#fff
style S4 fill:#e94560,stroke:#fff,color:#fff
style S4R fill:#ff9800,stroke:#fff,color:#fff
style S6 fill:#4CAF50,stroke:#fff,color:#fff
Hình 4: Redrive restart từ điểm thất bại, bỏ qua các bước đã thành công
Redrive hoạt động cho cả Standard Workflow lẫn child execution trong Distributed Map. Đặc biệt hữu ích khi batch job xử lý 1 triệu items và 5,000 items fail do transient error — thay vì chạy lại 1 triệu items, bạn chỉ redrive 5,000 items thất bại.
aws stepfunctions redrive-execution \
--execution-arn arn:aws:states:ap-southeast-1:123456:execution:OrderProcessing:exec-abc123
10. Best practices cho production
10.1. Thiết kế state machine idempotent
Dù Standard Workflow đảm bảo exactly-once, các service downstream (Lambda, DynamoDB, API bên thứ ba) vẫn có thể nhận duplicate request khi Step Functions retry. Mỗi Task state nên sử dụng idempotency key — ví dụ dùng execution name + state name làm key cho DynamoDB conditional write.
10.2. Giới hạn payload — 256KB
Step Functions giới hạn payload giữa các state ở 256KB. Với data lớn hơn, pattern chuẩn là lưu data vào S3 và chỉ truyền S3 key giữa các state. Đừng cố nhồi base64-encoded file vào state input — nó sẽ fail ở workflow thứ hai khi file lớn hơn.
// Pattern: S3 pointer thay vì inline data
{
"processedDataRef": {
"bucket": "my-processing-bucket",
"key": "results/2026-04/order-12345.json"
}
}
10.3. Observability — X-Ray tracing + CloudWatch Metrics
Bật X-Ray tracing cho state machine để có distributed trace xuyên suốt từ API Gateway → Step Functions → Lambda → DynamoDB. Kết hợp với CloudWatch Metrics để monitor:
ExecutionsFailed: Số workflow thất bại — set alarm khi vượt ngưỡngExecutionThrottled: Dấu hiệu cần request quota increaseExecutionTime: P99 execution time — detect workflow chậm bất thườngLambdaFunctionsFailed: Lambda nào trong workflow fail nhiều nhất
10.4. Versioning workflow an toàn
Step Functions hỗ trợ version và alias từ 2023. Khi cần deploy version mới của state machine, tạo version mới và chuyển alias dần dần — tương tự blue-green deployment. Các execution đang chạy tiếp tục trên version cũ, execution mới chạy trên version mới.
aws stepfunctions publish-state-machine-version \
--state-machine-arn arn:aws:states:ap-southeast-1:123456:stateMachine:OrderProcessing
aws stepfunctions update-state-machine-alias \
--state-machine-alias-arn arn:aws:states:ap-southeast-1:123456:stateMachine:OrderProcessing:prod \
--routing-configuration '[{"stateMachineVersionArn":"arn:...:3","weight":90},{"stateMachineVersionArn":"arn:...:4","weight":10}]'
11. So sánh Step Functions với các giải pháp khác
| Tiêu chí | Step Functions | Temporal | Apache Airflow | Azure Durable Functions |
|---|---|---|---|---|
| Deployment model | Fully managed serverless | Self-hosted hoặc Temporal Cloud | Self-hosted hoặc MWAA | Fully managed (Azure) |
| Workflow definition | JSON (ASL) | Code (Go, Java, TS, Python) | Python DAGs | Code (C#, JS, Python) |
| Max execution duration | 1 năm | Không giới hạn | Không giới hạn | Không giới hạn |
| Pricing | Per transition / per execution | Per action (Cloud) / infra cost (self-hosted) | Per environment hour (MWAA) | Per execution + duration |
| AWS integration | 220+ native | Qua SDK/API | Qua Operators | Azure-focused |
| Learning curve | Thấp (visual + JSON) | Cao (SDK patterns) | Trung bình (Python) | Trung bình (C#) |
| Best fit | AWS-native, serverless-first | Multi-cloud, complex logic | Data/ML pipeline | Azure ecosystem |
12. Kết luận
AWS Step Functions không phải là câu trả lời cho mọi bài toán orchestration. Nếu bạn cần workflow phức tạp với branching logic nặng và state management tinh vi, Temporal có thể phù hợp hơn. Nếu bạn đang xây ML pipeline, Airflow có ecosystem plugin phong phú hơn. Nhưng nếu hệ thống của bạn chạy trên AWS, yêu cầu serverless, và cần tích hợp sâu với các dịch vụ AWS khác — Step Functions là lựa chọn tự nhiên nhất.
Với bổ sung 1,100+ API actions mới trong tháng 3/2026 (bao gồm Bedrock AgentCore và S3 Vectors), Step Functions đang mở rộng từ "workflow orchestrator" thành "universal AWS service glue" — nơi bạn kết nối bất kỳ dịch vụ AWS nào với bất kỳ dịch vụ AWS nào khác, chỉ bằng JSON.
Bắt đầu từ đâu?
AWS Free Tier bao gồm 4,000 state transitions/tháng cho Standard Workflow — đủ để prototype và thử nghiệm. Sử dụng Workflow Studio trong AWS Console để thiết kế state machine trực quan, sau đó export ASL ra để version control trong Git.
Nguồn tham khảo:
Structured Logging trong .NET 10: Từ Console.WriteLine đến Hệ thống Log chuyên nghiệp với Serilog
Load Testing cho hệ thống phân tán — k6, NBomber và chiến lược kiểm thử hiệu năng
Disclaimer: The opinions expressed in this blog are solely my own and do not reflect the views or opinions of my employer or any affiliated organizations. The content provided is for informational and educational purposes only and should not be taken as professional advice. While I strive to provide accurate and up-to-date information, I make no warranties or guarantees about the completeness, reliability, or accuracy of the content. Readers are encouraged to verify the information and seek independent advice as needed. I disclaim any liability for decisions or actions taken based on the content of this blog.