-
-
Notifications
You must be signed in to change notification settings - Fork 62
Description
Description
While building a Saga pattern implementation using Durable Workflow, I noticed an excessively high number of database reads targeting the workflow logs. Although the queue messages and database writes are behaving as expected for an event-sourced architecture, the read volume grows exponentially as the workflow progresses, creating a potential bottleneck under high concurrency.
In a single execution of a relatively simple travel package workflow (3 sequential activities + 2 compensation activities triggered by an exception), the system executed 44 database reads for storedWorkflow->logs().
The Problem
Because Durable Workflow uses Event Sourcing to rebuild the state of the workflow every time it wakes up, it re-reads the event stream. However, it seems to be querying the database repeatedly instead of fetching the logs once per worker execution cycle.
Here is a summarized timeline of the event frequency for a single failed workflow execution (Saga pattern):
44x-read storedWorkflow->logs()🚩10x- Queue messages (activities, compensations, and exceptions)10x-write storedWorkflow->status("pending", "running", "waiting", "failed")
At a low volume, this is unnoticeable. But if 1,000 users trigger this workflow concurrently, it results in 44,000 database reads just to rehydrate states, which will quickly exhaust the database connection pool and spike CPU usage.
Steps to Reproduce
- Create a workflow that yields multiple sequential activities (e.g.,
HotelReservation,FlightReservation,TourGuideReservation). - Throw an exception in the last activity to trigger a
try/catchblock that queues compensation activities. - Monitor the database queries. You will see
SELECT * FROM workflow_logs WHERE ...being executed dozens of times for a single workflow lifecycle.
Environment:
- PHP Version: v8.4
- Laravel Version: v11.48.0
- Durable Workflow Version: v1.0.61